diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index 7c6bf5f8ac..508832b32b 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 2f35643c1a..9b78edf316 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 a5a0b2141b..646ea1acb6 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);