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