From 491f8215f19aca52b3e4e0f948da931480208d5e Mon Sep 17 00:00:00 2001
From: Luke Benstead <kazade@gmail.com>
Date: Sun, 24 May 2009 08:33:28 +0100
Subject: Separate IDirectDrawSurface(1) thunks

---
 dlls/ddraw/ddraw.c          |    1 +
 dlls/ddraw/ddraw_private.h  |    7 +
 dlls/ddraw/ddraw_thunks.c   |   21 ++-
 dlls/ddraw/surface.c        |   10 +-
 dlls/ddraw/surface_thunks.c |  551 ++++++++++++++++++++++++++++++++++++++-----
 5 files changed, 527 insertions(+), 63 deletions(-)

diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index e6db2c8..03c9237 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -1976,6 +1976,7 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This,
     }
     (*ppSurf)->lpVtbl = &IDirectDrawSurface7_Vtbl;
     (*ppSurf)->IDirectDrawSurface3_vtbl = &IDirectDrawSurface3_Vtbl;
+    (*ppSurf)->IDirectDrawSurface_vtbl = &IDirectDrawSurface_Vtbl;
     (*ppSurf)->IDirectDrawGammaControl_vtbl = &IDirectDrawGammaControl_Vtbl;
     (*ppSurf)->IDirect3DTexture2_vtbl = &IDirect3DTexture2_Vtbl;
     (*ppSurf)->IDirect3DTexture_vtbl = &IDirect3DTexture1_Vtbl;
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index 72dfff5..d802ccb 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -259,6 +259,7 @@ struct IDirectDrawSurfaceImpl
     /* IUnknown fields */
     const IDirectDrawSurface7Vtbl *lpVtbl;
     const IDirectDrawSurface3Vtbl *IDirectDrawSurface3_vtbl;
+    const IDirectDrawSurfaceVtbl *IDirectDrawSurface_vtbl;
     const IDirectDrawGammaControlVtbl *IDirectDrawGammaControl_vtbl;
     const IDirect3DTexture2Vtbl *IDirect3DTexture2_vtbl;
     const IDirect3DTextureVtbl *IDirect3DTexture_vtbl;
@@ -313,6 +314,7 @@ struct IDirectDrawSurfaceImpl
 /* VTable declaration. It's located in surface.c / surface_thunks.c */
 extern const IDirectDrawSurface7Vtbl IDirectDrawSurface7_Vtbl;
 extern const IDirectDrawSurface3Vtbl IDirectDrawSurface3_Vtbl;
+extern const IDirectDrawSurfaceVtbl IDirectDrawSurface_Vtbl;
 extern const IDirectDrawGammaControlVtbl IDirectDrawGammaControl_Vtbl;
 extern const IDirect3DTexture2Vtbl IDirect3DTexture2_Vtbl;
 extern const IDirect3DTextureVtbl IDirect3DTexture1_Vtbl;
@@ -330,6 +332,11 @@ static inline IDirectDrawSurfaceImpl *surface_from_texture2(IDirect3DTexture2 *i
     return (IDirectDrawSurfaceImpl *)((char*)iface - FIELD_OFFSET(IDirectDrawSurfaceImpl, IDirect3DTexture2_vtbl));
 }
 
+static inline IDirectDrawSurfaceImpl *surface_from_surface1(IDirectDrawSurface *iface)
+{
+    return (IDirectDrawSurfaceImpl *)((char*)iface - FIELD_OFFSET(IDirectDrawSurfaceImpl, IDirectDrawSurface_vtbl));
+}
+
 static inline IDirectDrawSurfaceImpl *surface_from_surface3(IDirectDrawSurface3 *iface)
 {
     return (IDirectDrawSurfaceImpl *)((char*)iface - FIELD_OFFSET(IDirectDrawSurfaceImpl, IDirectDrawSurface3_vtbl));
diff --git a/dlls/ddraw/ddraw_thunks.c b/dlls/ddraw/ddraw_thunks.c
index 8c79cbf..914fac1 100644
--- a/dlls/ddraw/ddraw_thunks.c
+++ b/dlls/ddraw/ddraw_thunks.c
@@ -348,10 +348,8 @@ IDirectDrawImpl_CreateSurface(LPDIRECTDRAW This, LPDDSURFACEDESC pSDesc,
     hr = IDirectDraw7_CreateSurface((IDirectDraw7 *)ddraw_from_ddraw1(This),
             (LPDDSURFACEDESC2)pSDesc, &pSurface7, pUnkOuter);
 
-    /* This coercion is safe, since the IDirectDrawSurface3 vtable has the
-     * IDirectDrawSurface vtable layout at the beginning  */
     *ppSurface = pSurface7 ?
-            (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)pSurface7)->IDirectDrawSurface3_vtbl : NULL;
+            (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)pSurface7)->IDirectDrawSurface_vtbl : NULL;
 
     impl = (IDirectDrawSurfaceImpl *)pSurface7;
     if(SUCCEEDED(hr) && impl)
@@ -585,6 +583,19 @@ EnumSurfacesCallbackThunk(LPDIRECTDRAWSURFACE7 pSurf, LPDDSURFACEDESC2 pDDSD,
     /* This coercion is safe, since the IDirectDrawSurface3 vtable has the
      * IDirectDrawSurface vtable layout at the beginning  */
     return cbcontext->func(
+            pSurf ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)pSurf)->IDirectDrawSurface_vtbl : NULL,
+            (LPDDSURFACEDESC)pDDSD, cbcontext->context);
+}
+
+static HRESULT CALLBACK
+EnumSurfacesCallbackThunk3(LPDIRECTDRAWSURFACE7 pSurf, LPDDSURFACEDESC2 pDDSD,
+			  LPVOID context)
+{
+    struct surfacescallback_context *cbcontext = context;
+
+    /* This coercion is safe, since the IDirectDrawSurface3 vtable has the
+     * IDirectDrawSurface vtable layout at the beginning  */
+    return cbcontext->func(
             pSurf ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)pSurf)->IDirectDrawSurface3_vtbl : NULL,
             (LPDDSURFACEDESC)pDDSD, cbcontext->context);
 }
@@ -614,7 +625,7 @@ IDirectDraw2Impl_EnumSurfaces(LPDIRECTDRAW2 This, DWORD dwFlags,
     cbcontext.context = context;
 
     return IDirectDraw7_EnumSurfaces((IDirectDraw7 *)ddraw_from_ddraw2(This),
-            dwFlags, (LPDDSURFACEDESC2)pDDSD, &cbcontext, EnumSurfacesCallbackThunk);
+            dwFlags, (LPDDSURFACEDESC2)pDDSD, &cbcontext, EnumSurfacesCallbackThunk3);
 }
 
 static HRESULT WINAPI
@@ -628,7 +639,7 @@ IDirectDraw3Impl_EnumSurfaces(LPDIRECTDRAW3 This, DWORD dwFlags,
     cbcontext.context = context;
 
     return IDirectDraw7_EnumSurfaces((IDirectDraw7 *)ddraw_from_ddraw3(This),
-            dwFlags, (LPDDSURFACEDESC2)pDDSD, &cbcontext, EnumSurfacesCallbackThunk);
+            dwFlags, (LPDDSURFACEDESC2)pDDSD, &cbcontext, EnumSurfacesCallbackThunk3);
 }
 
 static HRESULT WINAPI
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index bde2234..2d5901a 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -94,14 +94,20 @@ IDirectDrawSurfaceImpl_QueryInterface(IDirectDrawSurface7 *iface,
         return S_OK;
     }
     else if( IsEqualGUID(riid, &IID_IDirectDrawSurface3)
-          || IsEqualGUID(riid, &IID_IDirectDrawSurface2)
-          || IsEqualGUID(riid, &IID_IDirectDrawSurface) )
+          || IsEqualGUID(riid, &IID_IDirectDrawSurface2) )
     {
         IUnknown_AddRef(iface);
         *obj = &This->IDirectDrawSurface3_vtbl;
         TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
         return S_OK;
     }
+    else if( IsEqualGUID(riid, &IID_IDirectDrawSurface) )
+    {
+        *obj = &This->IDirectDrawSurface_vtbl;
+        IUnknown_AddRef((IUnknown*) *obj);
+        TRACE("(%p) returning IDirectDrawSurface(1) interface at %p\n", This, *obj);
+        return S_OK;
+    }
     else if( IsEqualGUID(riid, &IID_IDirectDrawGammaControl) )
     {
         IUnknown_AddRef(iface);
diff --git a/dlls/ddraw/surface_thunks.c b/dlls/ddraw/surface_thunks.c
index a7f61d0..fb0114b 100644
--- a/dlls/ddraw/surface_thunks.c
+++ b/dlls/ddraw/surface_thunks.c
@@ -33,6 +33,459 @@
 WINE_DEFAULT_DEBUG_CHANNEL(ddraw_thunk);
 WINE_DECLARE_DEBUG_CHANNEL(ddraw);
 
+struct callback_info
+{
+    LPDDENUMSURFACESCALLBACK callback;
+    LPVOID context;
+};
+
+static void DDSD_to_DDSD2(const DDSURFACEDESC *in, DDSURFACEDESC2 *out)
+{
+    memset(out, 0, sizeof(*out));
+    out->dwSize = sizeof(*out);
+    out->dwFlags = in->dwFlags;
+    if(in->dwFlags & DDSD_WIDTH) out->dwWidth = in->dwWidth;
+    if(in->dwFlags & DDSD_HEIGHT) out->dwHeight = in->dwHeight;
+    if(in->dwFlags & DDSD_PIXELFORMAT) out->ddpfPixelFormat = in->ddpfPixelFormat;
+    if(in->dwFlags & DDSD_CAPS) out->ddsCaps.dwCaps = in->ddsCaps.dwCaps;
+    if(in->dwFlags & DDSD_PITCH) out->lPitch = in->lPitch;
+    if(in->dwFlags & DDSD_BACKBUFFERCOUNT) out->dwBackBufferCount = in->dwBackBufferCount;
+    if(in->dwFlags & DDSD_ZBUFFERBITDEPTH) out->dwMipMapCount = in->dwZBufferBitDepth; /* same union */
+    if(in->dwFlags & DDSD_ALPHABITDEPTH) out->dwAlphaBitDepth = in->dwAlphaBitDepth;
+    /* DDraw(native, and wine) does not set the DDSD_LPSURFACE, so always copy */
+    out->lpSurface = in->lpSurface;
+    if(in->dwFlags & DDSD_CKDESTOVERLAY) out->ddckCKDestOverlay = in->ddckCKDestOverlay;
+    if(in->dwFlags & DDSD_CKDESTBLT) out->ddckCKDestBlt = in->ddckCKDestBlt;
+    if(in->dwFlags & DDSD_CKSRCOVERLAY) out->ddckCKSrcOverlay = in->ddckCKSrcOverlay;
+    if(in->dwFlags & DDSD_CKSRCBLT) out->ddckCKSrcBlt = in->ddckCKSrcBlt;
+    if(in->dwFlags & DDSD_MIPMAPCOUNT) out->dwMipMapCount = in->dwMipMapCount;
+    if(in->dwFlags & DDSD_REFRESHRATE) out->dwRefreshRate = in->dwRefreshRate;
+    if(in->dwFlags & DDSD_LINEARSIZE) out->dwLinearSize = in->dwLinearSize;
+    /* Does not exist in DDSURFACEDESC:
+     * DDSD_TEXTURESTAGE, DDSD_FVF, DDSD_SRCVBHANDLE,
+     */
+}
+
+static void DDSD2_to_DDSD(const DDSURFACEDESC2 *in, DDSURFACEDESC *out)
+{
+    memset(out, 0, sizeof(*out));
+    out->dwSize = sizeof(*out);
+    out->dwFlags = in->dwFlags;
+    if(in->dwFlags & DDSD_WIDTH) out->dwWidth = in->dwWidth;
+    if(in->dwFlags & DDSD_HEIGHT) out->dwHeight = in->dwHeight;
+    if(in->dwFlags & DDSD_PIXELFORMAT) out->ddpfPixelFormat = in->ddpfPixelFormat;
+    if(in->dwFlags & DDSD_CAPS) out->ddsCaps.dwCaps = in->ddsCaps.dwCaps;
+    if(in->dwFlags & DDSD_PITCH) out->lPitch = in->lPitch;
+    if(in->dwFlags & DDSD_BACKBUFFERCOUNT) out->dwBackBufferCount = in->dwBackBufferCount;
+    if(in->dwFlags & DDSD_ZBUFFERBITDEPTH) out->dwZBufferBitDepth = in->dwMipMapCount; /* same union */
+    if(in->dwFlags & DDSD_ALPHABITDEPTH) out->dwAlphaBitDepth = in->dwAlphaBitDepth;
+    /* DDraw(native, and wine) does not set the DDSD_LPSURFACE, so always copy */
+    out->lpSurface = in->lpSurface;
+    if(in->dwFlags & DDSD_CKDESTOVERLAY) out->ddckCKDestOverlay = in->ddckCKDestOverlay;
+    if(in->dwFlags & DDSD_CKDESTBLT) out->ddckCKDestBlt = in->ddckCKDestBlt;
+    if(in->dwFlags & DDSD_CKSRCOVERLAY) out->ddckCKSrcOverlay = in->ddckCKSrcOverlay;
+    if(in->dwFlags & DDSD_CKSRCBLT) out->ddckCKSrcBlt = in->ddckCKSrcBlt;
+    if(in->dwFlags & DDSD_MIPMAPCOUNT) out->dwMipMapCount = in->dwMipMapCount;
+    if(in->dwFlags & DDSD_REFRESHRATE) out->dwRefreshRate = in->dwRefreshRate;
+    if(in->dwFlags & DDSD_LINEARSIZE) out->dwLinearSize = in->dwLinearSize;
+    /* Does not exist in DDSURFACEDESC:
+     * DDSD_TEXTURESTAGE, DDSD_FVF, DDSD_SRCVBHANDLE,
+     */
+    if(in->dwFlags & DDSD_TEXTURESTAGE) WARN("Does not exist in DDSURFACEDESC: DDSD_TEXTURESTAGE\n");
+    if(in->dwFlags & DDSD_FVF) WARN("Does not exist in DDSURFACEDESC: DDSD_FVF\n");
+    if(in->dwFlags & DDSD_SRCVBHANDLE) WARN("Does not exist in DDSURFACEDESC: DDSD_SRCVBHANDLE\n");
+    out->dwFlags &= ~(DDSD_TEXTURESTAGE | DDSD_FVF | DDSD_SRCVBHANDLE);
+}
+
+static HRESULT CALLBACK
+EnumCallback(LPDIRECTDRAWSURFACE7 iface, LPDDSURFACEDESC2 pDDSD,
+         LPVOID context)
+{
+    const struct callback_info* info = context;
+
+    /* This is an outgoing conversion so we have to do it. */
+    DDSURFACEDESC ddsd;
+    DDSD2_to_DDSD(pDDSD, &ddsd);
+
+    return info->callback(iface ?
+            (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)iface)->IDirectDrawSurface_vtbl : NULL,
+            &ddsd, info->context);
+}
+
+static HRESULT CALLBACK
+EnumCallback3(LPDIRECTDRAWSURFACE7 iface, LPDDSURFACEDESC2 pDDSD,
+         LPVOID context)
+{
+    const struct callback_info* info = context;
+
+    /* This is an outgoing conversion so we have to do it. */
+    DDSURFACEDESC ddsd;
+    DDSD2_to_DDSD(pDDSD, &ddsd);
+
+    return info->callback(iface ?
+            (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)iface)->IDirectDrawSurface3_vtbl : NULL,
+            &ddsd, info->context);
+}
+
+/* IDirectDrawSurface thunks below */
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_QueryInterface(LPDIRECTDRAWSURFACE This, REFIID iid,
+                       LPVOID *ppObj)
+{
+    return IDirectDrawSurface7_QueryInterface((IDirectDrawSurface7 *)surface_from_surface1(This), iid, ppObj);
+}
+
+static ULONG WINAPI
+IDirectDrawSurface1Impl_AddRef(LPDIRECTDRAWSURFACE This)
+{
+    return IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)surface_from_surface1(This));
+}
+
+static ULONG WINAPI
+IDirectDrawSurface1Impl_Release(LPDIRECTDRAWSURFACE iface)
+{
+    IDirectDrawSurfaceImpl *This = surface_from_surface1(iface);
+    TRACE("(%p)\n", This);
+    return IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_AddAttachedSurface(LPDIRECTDRAWSURFACE iface,
+                       LPDIRECTDRAWSURFACE pAttach)
+{
+    IDirectDrawSurfaceImpl *This = surface_from_surface1(iface);
+    IDirectDrawSurfaceImpl *Surf = surface_from_surface1(pAttach);
+    TRACE("(%p)->(%p)\n", This, Surf);
+
+    /* Tests suggest that
+     * -> offscreen plain surfaces can be attached to other offscreen plain surfaces
+     * -> offscreen plain surfaces can be attached to primaries
+     * -> primaries can be attached to offscreen plain surfaces
+     * -> z buffers can be attached to primaries
+     *
+     */
+    if(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN) &&
+       Surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN))
+    {
+        /* Sizes have to match */
+        if(Surf->surface_desc.dwWidth != This->surface_desc.dwWidth ||
+        Surf->surface_desc.dwHeight != This->surface_desc.dwHeight)
+        {
+            WARN("Surface sizes do not match\n");
+            return DDERR_CANNOTATTACHSURFACE;
+        }
+        /* OK */
+    }
+    else if(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE) &&
+            Surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER))
+    {
+        /* OK */
+    }
+    else
+    {
+        WARN("Invalid attachment combination\n");
+        return DDERR_CANNOTATTACHSURFACE;
+    }
+
+    return IDirectDrawSurfaceImpl_AddAttachedSurface(This,
+                                                     Surf);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE This,
+                        LPRECT pRect)
+{
+    return IDirectDrawSurface7_AddOverlayDirtyRect((IDirectDrawSurface7 *)surface_from_surface1(This), pRect);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_Blt(LPDIRECTDRAWSURFACE This, LPRECT prcDst,
+                LPDIRECTDRAWSURFACE pSrcSurf, LPRECT prcSrc,
+                DWORD dwFlags, LPDDBLTFX pFX)
+{
+    return IDirectDrawSurface7_Blt((IDirectDrawSurface7 *)surface_from_surface1(This), prcDst,
+            pSrcSurf ? (IDirectDrawSurface7 *)surface_from_surface1(pSrcSurf) : NULL, prcSrc, dwFlags, pFX);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_BltBatch(LPDIRECTDRAWSURFACE This,
+                 LPDDBLTBATCH pBatch, DWORD dwCount,
+                 DWORD dwFlags)
+{
+    return IDirectDrawSurface7_BltBatch((IDirectDrawSurface7 *)surface_from_surface1(This), pBatch, dwCount, dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_BltFast(LPDIRECTDRAWSURFACE This, DWORD x, DWORD y,
+                LPDIRECTDRAWSURFACE pSrcSurf, LPRECT prcSrc,
+                DWORD dwTrans)
+{
+    return IDirectDrawSurface7_BltFast((IDirectDrawSurface7 *)surface_from_surface1(This), x, y,
+            pSrcSurf ? (IDirectDrawSurface7 *)surface_from_surface1(pSrcSurf) : NULL, prcSrc, dwTrans);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_DeleteAttachedSurface(LPDIRECTDRAWSURFACE This,
+                          DWORD dwFlags,
+                          LPDIRECTDRAWSURFACE pAttached)
+{
+    return IDirectDrawSurface7_DeleteAttachedSurface((IDirectDrawSurface7 *)surface_from_surface1(This), dwFlags,
+            pAttached ? (IDirectDrawSurface7 *)surface_from_surface1(pAttached) : NULL);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE This,
+                         LPVOID context,
+                         LPDDENUMSURFACESCALLBACK callback)
+{
+    struct callback_info info;
+
+    info.callback = callback;
+    info.context  = context;
+
+    return IDirectDrawSurface7_EnumAttachedSurfaces((IDirectDrawSurface7 *)surface_from_surface1(This),
+            &info, EnumCallback);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_EnumOverlayZOrders(LPDIRECTDRAWSURFACE This,
+                       DWORD dwFlags, LPVOID context,
+                       LPDDENUMSURFACESCALLBACK callback)
+{
+    struct callback_info info;
+
+    info.callback = callback;
+    info.context  = context;
+
+    return IDirectDrawSurface7_EnumOverlayZOrders((IDirectDrawSurface7 *)surface_from_surface1(This),
+            dwFlags, &info, EnumCallback);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_Flip(LPDIRECTDRAWSURFACE This,
+                 LPDIRECTDRAWSURFACE pOverride, DWORD dwFlags)
+{
+    return IDirectDrawSurface7_Flip((IDirectDrawSurface7 *)surface_from_surface1(This),
+            pOverride ? (IDirectDrawSurface7 *)surface_from_surface1(pOverride) : NULL, dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_GetAttachedSurface(LPDIRECTDRAWSURFACE This,
+                       LPDDSCAPS pCaps,
+                       LPDIRECTDRAWSURFACE* ppAttached)
+{
+    DDSCAPS2 caps;
+    LPDIRECTDRAWSURFACE7 pAttached7;
+    HRESULT hr;
+
+    caps.dwCaps  = pCaps->dwCaps;
+    caps.dwCaps2 = 0;
+    caps.dwCaps3 = 0;
+    caps.dwCaps4 = 0;
+
+    hr = IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)surface_from_surface1(This), &caps, &pAttached7);
+    if (FAILED(hr)) *ppAttached = NULL;
+    else *ppAttached = pAttached7 ?
+            (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)pAttached7)->IDirectDrawSurface_vtbl : NULL;
+    return hr;
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_GetBltStatus(LPDIRECTDRAWSURFACE This, DWORD dwFlags)
+{
+    return IDirectDrawSurface7_GetBltStatus((IDirectDrawSurface7 *)surface_from_surface1(This), dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_GetCaps(LPDIRECTDRAWSURFACE This, LPDDSCAPS pCaps)
+{
+    DDSCAPS2 caps;
+    HRESULT hr;
+
+    hr = IDirectDrawSurface7_GetCaps((IDirectDrawSurface7 *)surface_from_surface1(This), &caps);
+    if (FAILED(hr)) return hr;
+
+    pCaps->dwCaps = caps.dwCaps;
+    return hr;
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_GetClipper(LPDIRECTDRAWSURFACE This,
+                   LPDIRECTDRAWCLIPPER* ppClipper)
+{
+    return IDirectDrawSurface7_GetClipper((IDirectDrawSurface7 *)surface_from_surface1(This), ppClipper);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_GetColorKey(LPDIRECTDRAWSURFACE This, DWORD dwFlags,
+                    LPDDCOLORKEY pCKey)
+{
+    return IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)surface_from_surface1(This), dwFlags, pCKey);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_GetDC(LPDIRECTDRAWSURFACE This, HDC* phDC)
+{
+    return IDirectDrawSurface7_GetDC((IDirectDrawSurface7 *)surface_from_surface1(This), phDC);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_GetFlipStatus(LPDIRECTDRAWSURFACE This, DWORD dwFlags)
+{
+    return IDirectDrawSurface7_GetFlipStatus((IDirectDrawSurface7 *)surface_from_surface1(This), dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_GetOverlayPosition(LPDIRECTDRAWSURFACE This, LPLONG pX,
+                       LPLONG pY)
+{
+    return IDirectDrawSurface7_GetOverlayPosition((IDirectDrawSurface7 *)surface_from_surface1(This), pX, pY);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_GetPalette(LPDIRECTDRAWSURFACE This,
+                   LPDIRECTDRAWPALETTE* ppPalette)
+{
+    return IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)surface_from_surface1(This), ppPalette);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_GetPixelFormat(LPDIRECTDRAWSURFACE This,
+                       LPDDPIXELFORMAT pPixelFormat)
+{
+    return IDirectDrawSurface7_GetPixelFormat((IDirectDrawSurface7 *)surface_from_surface1(This), pPixelFormat);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_GetSurfaceDesc(LPDIRECTDRAWSURFACE iface,
+                       LPDDSURFACEDESC pDDSD)
+{
+    IDirectDrawSurfaceImpl *This = surface_from_surface1(iface);
+    DDSURFACEDESC2 DDSD2;
+    HRESULT result;
+    
+    if(!pDDSD)
+        return DDERR_INVALIDPARAMS;
+
+    if (pDDSD->dwSize != sizeof(DDSURFACEDESC))
+    {
+        WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",pDDSD->dwSize);
+        return DDERR_INVALIDPARAMS;
+    }
+    
+    /* Convert the surface desc to version 2 */
+    DDSD_to_DDSD2(pDDSD, &DDSD2);
+    
+    /* Call the 7 version of GetSurfaceDesc */
+    result = IDirectDrawSurface7_GetSurfaceDesc((IDirectDrawSurface7 *)This, &DDSD2);
+    
+    if (SUCCEEDED(result))
+    {
+        /* Copy the result back */
+        DDSD2_to_DDSD(&DDSD2, pDDSD);
+    }
+    
+    return result;
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_Initialize(LPDIRECTDRAWSURFACE This, LPDIRECTDRAW pDD,
+                   LPDDSURFACEDESC pDDSD)
+{
+    return IDirectDrawSurface7_Initialize((IDirectDrawSurface7 *)surface_from_surface1(This),
+            pDD, (LPDDSURFACEDESC2)pDDSD);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_IsLost(LPDIRECTDRAWSURFACE This)
+{
+    return IDirectDrawSurface7_IsLost((IDirectDrawSurface7 *)surface_from_surface1(This));
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_Lock(LPDIRECTDRAWSURFACE This, LPRECT pRect,
+                 LPDDSURFACEDESC pDDSD, DWORD dwFlags, HANDLE h)
+{
+    return IDirectDrawSurface7_Lock((IDirectDrawSurface7 *)surface_from_surface1(This),
+            pRect, (LPDDSURFACEDESC2)pDDSD, dwFlags, h);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_ReleaseDC(LPDIRECTDRAWSURFACE This, HDC hDC)
+{
+    return IDirectDrawSurface7_ReleaseDC((IDirectDrawSurface7 *)surface_from_surface1(This), hDC);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_Restore(LPDIRECTDRAWSURFACE This)
+{
+    return IDirectDrawSurface7_Restore((IDirectDrawSurface7 *)surface_from_surface1(This));
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_SetClipper(LPDIRECTDRAWSURFACE This,
+                   LPDIRECTDRAWCLIPPER pClipper)
+{
+    return IDirectDrawSurface7_SetClipper((IDirectDrawSurface7 *)surface_from_surface1(This), pClipper);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_SetColorKey(LPDIRECTDRAWSURFACE This, DWORD dwFlags,
+                    LPDDCOLORKEY pCKey)
+{
+    return IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)surface_from_surface1(This), dwFlags, pCKey);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_SetOverlayPosition(LPDIRECTDRAWSURFACE This, LONG x,
+                       LONG y)
+{
+    return IDirectDrawSurface7_SetOverlayPosition((IDirectDrawSurface7 *)surface_from_surface1(This), x, y);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_SetPalette(LPDIRECTDRAWSURFACE This,
+                   LPDIRECTDRAWPALETTE pPalette)
+{
+    return IDirectDrawSurface7_SetPalette((IDirectDrawSurface7 *)surface_from_surface1(This), pPalette);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_Unlock(LPDIRECTDRAWSURFACE This, LPVOID data)
+{
+    /* data might not be the LPRECT of later versions, so drop it. */
+    return IDirectDrawSurface7_Unlock((IDirectDrawSurface7 *)surface_from_surface1(This), NULL);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_UpdateOverlay(LPDIRECTDRAWSURFACE This, LPRECT prcSrc,
+                      LPDIRECTDRAWSURFACE pDstSurf,
+                      LPRECT prcDst, DWORD dwFlags,
+                      LPDDOVERLAYFX pFX)
+{
+    return IDirectDrawSurface7_UpdateOverlay((IDirectDrawSurface7 *)surface_from_surface1(This), prcSrc,
+            pDstSurf ? (IDirectDrawSurface7 *)surface_from_surface1(pDstSurf) : NULL, prcDst, dwFlags, pFX);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE This,
+                         DWORD dwFlags)
+{
+    return IDirectDrawSurface7_UpdateOverlayDisplay((IDirectDrawSurface7 *)surface_from_surface1(This), dwFlags);
+}
+
+static HRESULT WINAPI
+IDirectDrawSurface1Impl_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE This,
+                        DWORD dwFlags,
+                        LPDIRECTDRAWSURFACE pSurfReference)
+{
+    return IDirectDrawSurface7_UpdateOverlayZOrder((IDirectDrawSurface7 *)surface_from_surface1(This), dwFlags,
+            pSurfReference ? (IDirectDrawSurface7 *)surface_from_surface1(pSurfReference) : NULL);
+}
+
+/* IDirectDrawSurface3 thunks below */
+
 static HRESULT WINAPI
 IDirectDrawSurface3Impl_QueryInterface(LPDIRECTDRAWSURFACE3 This, REFIID iid,
                        LPVOID *ppObj)
@@ -138,60 +591,6 @@ IDirectDrawSurface3Impl_DeleteAttachedSurface(LPDIRECTDRAWSURFACE3 This,
             pAttached ? (IDirectDrawSurface7 *)surface_from_surface3(pAttached) : NULL);
 }
 
-static void DDSD2_to_DDSD(const DDSURFACEDESC2 *in, DDSURFACEDESC *out)
-{
-    memset(out, 0, sizeof(*out));
-    out->dwSize = sizeof(*out);
-    out->dwFlags = in->dwFlags;
-    if(in->dwFlags & DDSD_WIDTH) out->dwWidth = in->dwWidth;
-    if(in->dwFlags & DDSD_HEIGHT) out->dwHeight = in->dwHeight;
-    if(in->dwFlags & DDSD_PIXELFORMAT) out->ddpfPixelFormat = in->ddpfPixelFormat;
-    if(in->dwFlags & DDSD_CAPS) out->ddsCaps.dwCaps = in->ddsCaps.dwCaps;
-    if(in->dwFlags & DDSD_PITCH) out->lPitch = in->lPitch;
-    if(in->dwFlags & DDSD_BACKBUFFERCOUNT) out->dwBackBufferCount = in->dwBackBufferCount;
-    if(in->dwFlags & DDSD_ZBUFFERBITDEPTH) out->dwZBufferBitDepth = in->dwMipMapCount; /* same union */
-    if(in->dwFlags & DDSD_ALPHABITDEPTH) out->dwAlphaBitDepth = in->dwAlphaBitDepth;
-    /* DDraw(native, and wine) does not set the DDSD_LPSURFACE, so always copy */
-    out->lpSurface = in->lpSurface;
-    if(in->dwFlags & DDSD_CKDESTOVERLAY) out->ddckCKDestOverlay = in->ddckCKDestOverlay;
-    if(in->dwFlags & DDSD_CKDESTBLT) out->ddckCKDestBlt = in->ddckCKDestBlt;
-    if(in->dwFlags & DDSD_CKSRCOVERLAY) out->ddckCKSrcOverlay = in->ddckCKSrcOverlay;
-    if(in->dwFlags & DDSD_CKSRCBLT) out->ddckCKSrcBlt = in->ddckCKSrcBlt;
-    if(in->dwFlags & DDSD_MIPMAPCOUNT) out->dwMipMapCount = in->dwMipMapCount;
-    if(in->dwFlags & DDSD_REFRESHRATE) out->dwRefreshRate = in->dwRefreshRate;
-    if(in->dwFlags & DDSD_LINEARSIZE) out->dwLinearSize = in->dwLinearSize;
-    /* Does not exist in DDSURFACEDESC:
-     * DDSD_TEXTURESTAGE, DDSD_FVF, DDSD_SRCVBHANDLE,
-     */
-    if(in->dwFlags & DDSD_TEXTURESTAGE) WARN("Does not exist in DDSURFACEDESC: DDSD_TEXTURESTAGE\n");
-    if(in->dwFlags & DDSD_FVF) WARN("Does not exist in DDSURFACEDESC: DDSD_FVF\n");
-    if(in->dwFlags & DDSD_SRCVBHANDLE) WARN("Does not exist in DDSURFACEDESC: DDSD_SRCVBHANDLE\n");
-    out->dwFlags &= ~(DDSD_TEXTURESTAGE | DDSD_FVF | DDSD_SRCVBHANDLE);
-}
-
-struct callback_info
-{
-    LPDDENUMSURFACESCALLBACK callback;
-    LPVOID context;
-};
-
-static HRESULT CALLBACK
-EnumCallback(LPDIRECTDRAWSURFACE7 iface, LPDDSURFACEDESC2 pDDSD,
-         LPVOID context)
-{
-    const struct callback_info* info = context;
-
-    /* This is an outgoing conversion so we have to do it. */
-    DDSURFACEDESC ddsd;
-    DDSD2_to_DDSD(pDDSD, &ddsd);
-
-    /* the LPDDSURFACEDESC2 -> LPDDSURFACEDESC coercion is safe, since
-     * the data format is compatible with older enum procs */
-    return info->callback(iface ?
-            (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)iface)->IDirectDrawSurface3_vtbl : NULL,
-            &ddsd, info->context);
-}
-
 static HRESULT WINAPI
 IDirectDrawSurface3Impl_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE3 This,
                          LPVOID context,
@@ -203,7 +602,7 @@ IDirectDrawSurface3Impl_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE3 This,
     info.context  = context;
 
     return IDirectDrawSurface7_EnumAttachedSurfaces((IDirectDrawSurface7 *)surface_from_surface3(This),
-            &info, EnumCallback);
+            &info, EnumCallback3);
 }
 
 static HRESULT WINAPI
@@ -217,7 +616,7 @@ IDirectDrawSurface3Impl_EnumOverlayZOrders(LPDIRECTDRAWSURFACE3 This,
     info.context  = context;
 
     return IDirectDrawSurface7_EnumOverlayZOrders((IDirectDrawSurface7 *)surface_from_surface3(This),
-            dwFlags, &info, EnumCallback);
+            dwFlags, &info, EnumCallback3);
 }
 
 static HRESULT WINAPI
@@ -466,6 +865,46 @@ IDirectDrawSurface3Impl_SetSurfaceDesc(LPDIRECTDRAWSURFACE3 This,
             (LPDDSURFACEDESC2)pDDSD, dwFlags);
 }
 
+const IDirectDrawSurfaceVtbl IDirectDrawSurface_Vtbl = 
+{
+    IDirectDrawSurface1Impl_QueryInterface,
+    IDirectDrawSurface1Impl_AddRef,
+    IDirectDrawSurface1Impl_Release,
+    IDirectDrawSurface1Impl_AddAttachedSurface,
+    IDirectDrawSurface1Impl_AddOverlayDirtyRect,
+    IDirectDrawSurface1Impl_Blt,
+    IDirectDrawSurface1Impl_BltBatch,
+    IDirectDrawSurface1Impl_BltFast,
+    IDirectDrawSurface1Impl_DeleteAttachedSurface,
+    IDirectDrawSurface1Impl_EnumAttachedSurfaces,
+    IDirectDrawSurface1Impl_EnumOverlayZOrders,
+    IDirectDrawSurface1Impl_Flip,
+    IDirectDrawSurface1Impl_GetAttachedSurface,
+    IDirectDrawSurface1Impl_GetBltStatus,
+    IDirectDrawSurface1Impl_GetCaps,
+    IDirectDrawSurface1Impl_GetClipper,
+    IDirectDrawSurface1Impl_GetColorKey,
+    IDirectDrawSurface1Impl_GetDC,
+    IDirectDrawSurface1Impl_GetFlipStatus,
+    IDirectDrawSurface1Impl_GetOverlayPosition,
+    IDirectDrawSurface1Impl_GetPalette,
+    IDirectDrawSurface1Impl_GetPixelFormat,
+    IDirectDrawSurface1Impl_GetSurfaceDesc,
+    IDirectDrawSurface1Impl_Initialize,
+    IDirectDrawSurface1Impl_IsLost,
+    IDirectDrawSurface1Impl_Lock,
+    IDirectDrawSurface1Impl_ReleaseDC,
+    IDirectDrawSurface1Impl_Restore,
+    IDirectDrawSurface1Impl_SetClipper,
+    IDirectDrawSurface1Impl_SetColorKey,
+    IDirectDrawSurface1Impl_SetOverlayPosition,
+    IDirectDrawSurface1Impl_SetPalette,
+    IDirectDrawSurface1Impl_Unlock,
+    IDirectDrawSurface1Impl_UpdateOverlay,
+    IDirectDrawSurface1Impl_UpdateOverlayDisplay,
+    IDirectDrawSurface1Impl_UpdateOverlayZOrder
+};
+
 const IDirectDrawSurface3Vtbl IDirectDrawSurface3_Vtbl =
 {
     IDirectDrawSurface3Impl_QueryInterface,
-- 
1.6.0.4

