Stefan Dösinger : ddraw: Cope with Init3D failures.

Alexandre Julliard julliard at winehq.org
Wed Oct 10 06:46:15 CDT 2007


Module: wine
Branch: master
Commit: c5055fb3eb59b951898d7408fae0d9461313e397
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c5055fb3eb59b951898d7408fae0d9461313e397

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Tue Oct  9 14:42:06 2007 +0200

ddraw: Cope with Init3D failures.

---

 dlls/ddraw/ddraw.c         |   29 ++++++++++++++++++++++++-----
 dlls/ddraw/ddraw_private.h |    1 +
 dlls/ddraw/surface.c       |    2 +-
 3 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 7c6bf5f..508832b 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -2519,10 +2519,6 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface,
         return hr;
     }
 
-    /* Addref the ddraw interface to keep an reference for each surface */
-    IDirectDraw7_AddRef(iface);
-    object->ifaceToRelease = (IUnknown *) iface;
-
     /* If the implementation is OpenGL and there's no d3ddevice, attach a d3ddevice
      * But attach the d3ddevice only if the currently created surface was
      * a primary surface (2D app in 3D mode) or a 3DDEVICE surface (3D app)
@@ -2555,10 +2551,32 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface,
         hr = IDirectDrawImpl_AttachD3DDevice(This, target);
         if(hr != D3D_OK)
         {
+            IDirectDrawSurfaceImpl *release_surf;
             ERR("IDirectDrawImpl_AttachD3DDevice failed, hr = %x\n", hr);
+            *Surf = NULL;
+
+            /* The before created surface structures are in an incomplete state here.
+             * WineD3D holds the reference on the IParents, and it released them on the failure
+             * already. So the regular release method implementation would fail on the attempt
+             * to destroy either the IParents or the swapchain. So free the surface here.
+             * The surface structure here is a list, not a tree, because onscreen targets
+             * cannot be cube textures
+             */
+            while(object)
+            {
+                release_surf = object;
+                object = object->complex_array[0];
+                IDirectDrawSurfaceImpl_Destroy(release_surf);
+            }
+            LeaveCriticalSection(&ddraw_cs);
+            return hr;
         }
     }
 
+    /* Addref the ddraw interface to keep an reference for each surface */
+    IDirectDraw7_AddRef(iface);
+    object->ifaceToRelease = (IUnknown *) iface;
+
     /* Create a WineD3DTexture if a texture was requested */
     if(desc2.ddsCaps.dwCaps & DDSCAPS_TEXTURE)
     {
@@ -3077,7 +3095,8 @@ IDirectDrawImpl_AttachD3DDevice(IDirectDrawImpl *This,
                                D3D7CB_CreateAdditionalSwapChain);
     if(FAILED(hr))
     {
-        This->wineD3DDevice = NULL;
+        This->d3d_target = NULL;
+        This->d3d_initialized = FALSE;
         return hr;
     }
 
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index 2f35643..9b78edf 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -273,6 +273,7 @@ const IDirect3DTexture2Vtbl IDirect3DTexture2_Vtbl;
 const IDirect3DTextureVtbl IDirect3DTexture1_Vtbl;
 
 HRESULT WINAPI IDirectDrawSurfaceImpl_AddAttachedSurface(IDirectDrawSurfaceImpl *This, IDirectDrawSurfaceImpl *Surf);
+void IDirectDrawSurfaceImpl_Destroy(IDirectDrawSurfaceImpl *This);
 
 /* Get the number of bytes per pixel for a given surface */
 #define PFGET_BPP(pf) (pf.dwFlags&DDPF_PALETTEINDEXED8?1:((pf.dwRGBBitCount+7)/8))
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index a5a0b21..646ea1a 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -178,7 +178,7 @@ IDirectDrawSurfaceImpl_AddRef(IDirectDrawSurface7 *iface)
  *  This: Surface to free
  *
  *****************************************************************************/
-static void IDirectDrawSurfaceImpl_Destroy(IDirectDrawSurfaceImpl *This)
+void IDirectDrawSurfaceImpl_Destroy(IDirectDrawSurfaceImpl *This)
 {
     TRACE("(%p)\n", This);
 




More information about the wine-cvs mailing list