ddraw: Use QueryInterface rather than casting from the DDS3 vtbl (needed to fix ddraw surface refcounting)

Luke Benstead kazade at gmail.com
Mon Jun 28 14:28:47 CDT 2010


Luke.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-patches/attachments/20100628/72f8ddbb/attachment.htm>
-------------- next part --------------
From 7cf888f3c918f2d96bf842be2f83679a69334334 Mon Sep 17 00:00:00 2001
From: Luke Benstead <kazade at gmail.com>
Date: Mon, 28 Jun 2010 19:23:30 +0100
Subject: ddraw: Use QueryInterface rather than casting from the DDS3 vtbl (needed to fix ddraw surface refcounting)

---
 dlls/ddraw/ddraw_thunks.c |  119 ++++++++++++++++++++++++++++++++------------
 1 files changed, 86 insertions(+), 33 deletions(-)

diff --git a/dlls/ddraw/ddraw_thunks.c b/dlls/ddraw/ddraw_thunks.c
index 28991d1..b3db778 100644
--- a/dlls/ddraw/ddraw_thunks.c
+++ b/dlls/ddraw/ddraw_thunks.c
@@ -354,7 +354,8 @@ IDirectDrawImpl_CreateSurface(LPDIRECTDRAW This, LPDDSURFACEDESC pSDesc,
     }
 
     impl = (IDirectDrawSurfaceImpl *)pSurface7;
-    *ppSurface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
+    IDirectDrawSurface7_QueryInterface(pSurface7, &IID_IDirectDrawSurface, (void**) ppSurface);
+    IDirectDrawSurface7_Release(pSurface7);
     set_surf_version(impl, 1);
     IDirectDraw7_Release((IDirectDraw7 *)ddraw_from_ddraw1(This));
     impl->ifaceToRelease = NULL;
@@ -380,7 +381,10 @@ IDirectDraw2Impl_CreateSurface(LPDIRECTDRAW2 This, LPDDSURFACEDESC pSDesc,
     }
 
     impl = (IDirectDrawSurfaceImpl *)pSurface7;
-    *ppSurface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
+
+    IDirectDrawSurface7_QueryInterface(pSurface7, &IID_IDirectDrawSurface2, (void**) ppSurface);
+    IDirectDrawSurface7_Release(pSurface7);
+
     set_surf_version(impl, 2);
     IDirectDraw7_Release((IDirectDraw7 *)ddraw_from_ddraw2(This));
     impl->ifaceToRelease = NULL;
@@ -406,7 +410,10 @@ IDirectDraw3Impl_CreateSurface(LPDIRECTDRAW3 This, LPDDSURFACEDESC pSDesc,
     }
 
     impl = (IDirectDrawSurfaceImpl *)pSurface7;
-    *ppSurface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
+
+    IDirectDrawSurface7_QueryInterface(pSurface7, &IID_IDirectDrawSurface3, (void**) ppSurface);
+    IDirectDrawSurface7_Release(pSurface7);
+
     set_surf_version(impl, 3);
     IDirectDraw7_Release((IDirectDraw7 *)ddraw_from_ddraw3(This));
     IDirectDraw3_AddRef(This);
@@ -421,18 +428,28 @@ IDirectDraw4Impl_CreateSurface(LPDIRECTDRAW4 This, LPDDSURFACEDESC2 pSDesc,
 			       IUnknown *pUnkOuter)
 {
     HRESULT hr;
+    LPDIRECTDRAWSURFACE7 pSurface7;
     IDirectDrawSurfaceImpl *impl;
 
     hr = IDirectDraw7_CreateSurface((IDirectDraw7 *)ddraw_from_ddraw4(This),
-            pSDesc, (LPDIRECTDRAWSURFACE7 *)ppSurface, pUnkOuter);
-    impl = (IDirectDrawSurfaceImpl *)*ppSurface;
-    if(SUCCEEDED(hr) && impl)
+            pSDesc, &pSurface7, pUnkOuter);
+
+    if (FAILED(hr))
     {
-        set_surf_version(impl, 4);
-        IDirectDraw7_Release((IDirectDraw7 *)ddraw_from_ddraw4(This));
-        IDirectDraw4_AddRef(This);
-        impl->ifaceToRelease = (IUnknown *) This;
+        *ppSurface = NULL;
+        return hr;
     }
+
+    impl = (IDirectDrawSurfaceImpl *)pSurface7;
+
+    IDirectDrawSurface7_QueryInterface(pSurface7, &IID_IDirectDrawSurface4, (void**) ppSurface);
+    IDirectDrawSurface7_Release(pSurface7);
+
+    set_surf_version(impl, 4);
+    IDirectDraw7_Release((IDirectDraw7 *)ddraw_from_ddraw4(This));
+    IDirectDraw4_AddRef(This);
+    impl->ifaceToRelease = (IUnknown *) This;
+
     return hr;
 }
 
@@ -446,9 +463,13 @@ IDirectDrawImpl_DuplicateSurface(LPDIRECTDRAW This, LPDIRECTDRAWSURFACE pSrc,
     hr = IDirectDraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw1(This),
             pSrc ? (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)pSrc) : NULL, &pDst7);
 
-    /* This coercion is safe, since the IDirectDrawSurface3 vtable has the
-     * IDirectDrawSurface vtable layout at the beginning  */
-    *ppDst = pDst7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)pDst7)->IDirectDrawSurface3_vtbl : NULL;
+    if(pDst7)
+    {
+        IDirectDrawSurface7_QueryInterface(pDst7, &IID_IDirectDrawSurface, (void**) ppDst);
+        IDirectDrawSurface7_Release(pDst7);
+    }
+    else
+        *ppDst = NULL;
 
     return hr;
 }
@@ -463,9 +484,13 @@ IDirectDraw2Impl_DuplicateSurface(LPDIRECTDRAW2 This, LPDIRECTDRAWSURFACE pSrc,
     hr = IDirectDraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw2(This),
             pSrc ? (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)pSrc) : NULL, &pDst7);
 
-    /* This coercion is safe, since the IDirectDrawSurface3 vtable has the
-     * IDirectDrawSurface vtable layout at the beginning  */
-    *ppDst = pDst7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)pDst7)->IDirectDrawSurface3_vtbl : NULL;
+    if(pDst7)
+    {
+        IDirectDrawSurface7_QueryInterface(pDst7, &IID_IDirectDrawSurface2, (void**) ppDst);
+        IDirectDrawSurface7_Release(pDst7);
+    }
+    else
+        *ppDst = NULL;
 
     return hr;
 }
@@ -480,10 +505,14 @@ IDirectDraw3Impl_DuplicateSurface(LPDIRECTDRAW3 This, LPDIRECTDRAWSURFACE pSrc,
     hr = IDirectDraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw3(This),
             pSrc ? (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)pSrc) : NULL, &pDst7);
 
-    /* This coercion is safe, since the IDirectDrawSurface3 vtable has the
-     * IDirectDrawSurface vtable layout at the beginning  */
-    *ppDst = pDst7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)pDst7)->IDirectDrawSurface3_vtbl : NULL;
-
+    if(pDst7)
+    {
+        IDirectDrawSurface7_QueryInterface(pDst7, &IID_IDirectDrawSurface3, (void**) ppDst);
+        IDirectDrawSurface7_Release(pDst7);
+    }
+    else
+        *ppDst = NULL;
+        
     return hr;
 }
 
@@ -492,8 +521,20 @@ IDirectDraw4Impl_DuplicateSurface(LPDIRECTDRAW4 This,
 				  LPDIRECTDRAWSURFACE4 pSrc,
 				  LPDIRECTDRAWSURFACE4 *ppDst)
 {
-    return IDirectDraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw4(This),
-            (LPDIRECTDRAWSURFACE7)pSrc, (LPDIRECTDRAWSURFACE7 *)ppDst);
+    LPDIRECTDRAWSURFACE7 pDst7;
+    HRESULT hr;
+    hr = IDirectDraw7_DuplicateSurface((IDirectDraw7 *)ddraw_from_ddraw4(This),
+            (LPDIRECTDRAWSURFACE7)pSrc, (LPDIRECTDRAWSURFACE7 *)&pDst7);
+            
+    if(pDst7)
+    {
+        IDirectDrawSurface7_QueryInterface(pDst7, &IID_IDirectDrawSurface4, (void**) ppDst);
+        IDirectDrawSurface7_Release(pDst7);
+    }
+    else
+        *ppDst = NULL;            
+        
+    return hr;
 }
 
 struct displaymodescallback_context
@@ -742,10 +783,14 @@ IDirectDrawImpl_GetGDISurface(LPDIRECTDRAW This, LPDIRECTDRAWSURFACE *ppSurf)
 
     hr = IDirectDraw7_GetGDISurface((IDirectDraw7 *)ddraw_from_ddraw1(This), &pSurf7);
 
-    /* This coercion is safe, since the IDirectDrawSurface3 vtable has the
-     * IDirectDrawSurface vtable layout at the beginning  */
-    *ppSurf = pSurf7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)pSurf7)->IDirectDrawSurface3_vtbl : NULL;
-
+    if(pSurf7)
+    {
+        IDirectDrawSurface7_QueryInterface(pSurf7, &IID_IDirectDrawSurface, (void**) ppSurf);
+        IDirectDrawSurface7_Release(pSurf7);
+    }
+    else
+        *ppSurf = NULL;
+        
     return hr;
 }
 
@@ -757,9 +802,13 @@ IDirectDraw2Impl_GetGDISurface(LPDIRECTDRAW2 This, LPDIRECTDRAWSURFACE *ppSurf)
 
     hr = IDirectDraw7_GetGDISurface((IDirectDraw7 *)ddraw_from_ddraw2(This), &pSurf7);
 
-    /* This coercion is safe, since the IDirectDrawSurface3 vtable has the
-     * IDirectDrawSurface vtable layout at the beginning  */
-    *ppSurf = pSurf7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)pSurf7)->IDirectDrawSurface3_vtbl : NULL;
+    if(pSurf7)
+    {
+        IDirectDrawSurface2_QueryInterface(pSurf7, &IID_IDirectDrawSurface2, (void**) ppSurf);
+        IDirectDrawSurface7_Release(pSurf7);
+    } 
+    else
+        *ppSurf = NULL;
 
     return hr;
 }
@@ -772,10 +821,14 @@ IDirectDraw3Impl_GetGDISurface(LPDIRECTDRAW3 This, LPDIRECTDRAWSURFACE *ppSurf)
 
     hr = IDirectDraw7_GetGDISurface((IDirectDraw7 *)ddraw_from_ddraw3(This), &pSurf7);
 
-    /* This coercion is safe, since the IDirectDrawSurface3 vtable has the
-     * IDirectDrawSurface vtable layout at the beginning  */
-    *ppSurf = pSurf7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)pSurf7)->IDirectDrawSurface3_vtbl : NULL;
-
+    if(pSurf7)
+    {
+        IDirectDrawSurface3_QueryInterface(pSurf7, &IID_IDirectDrawSurface3, (void**) ppSurf);
+        IDirectDrawSurface7_Release(pSurf7);
+    } 
+    else
+        *ppSurf = NULL;
+    
     return hr;
 }
 
-- 
1.7.0.4


More information about the wine-patches mailing list