ddraw: [3/3] Fix for regression bug #13277

Stefan Dösinger stefan at codeweavers.com
Sat May 24 10:30:47 CDT 2008

> +    ref = getRefcount(lpDD);
> +    ok(ref == 1, "Got refcount %ld, expected 2\n", ref);
> +    
> +    IDirectDraw_Release(lpDD);
> +    
> +    ref = getRefcount(lpDD);
> +    ok(ref == 0, "Got refcount %ld, expected 1\n", ref);
I think there's a copypaste error, it seems you forgot to adjust the error 

Your test shows the correctness of the patch pretty well, although out of 
curiosity, can you try this: Between the IDirectDraw_Release(), which reduces 
the refcount to 0 and the ref = getRefcount(), can you try to HeapAlloc() 
small portions(e.g. 512 bytes) of memory with HEAP_ZERO_MEMORY until you get 
an out of memory error. This should make it less likely that the lpDD object 
survives by luck. It might be destroyed by windows, but the memory is not yet 
overwritten by something else, so the getRefcount works by luck. If this does 
not lead to a crash, try the memory allocation + getRefcount again after the 
Surface::Release call below, there it should cause a crash.

> @@ -1998,6 +2026,13 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl 
>     InterlockedIncrement(&This->surfaces);
>     list_add_head(&This->surface_list, &(*ppSurf)->surface_list_entry);
> +    IDirectDrawInternal_AddRef(This);

> @@ -424,6 +424,9 @@ IDirectDrawSurfaceImpl_Release(IDirectDrawSurface7 
>          /* Reduce the ddraw refcount */
>          if(ifaceToRelease) IUnknown_Release(ifaceToRelease);
>          LeaveCriticalSection(&ddraw_cs);
> +        
> +        /* Surface does not need ddraw anymore, release it's reference */
> +        IDirectDrawInternal_Release(ddraw);
The counterpart to IDirectDrawImpl_CreateNewSurface is 
IDirectDrawSurfaceImpl_Destroy, not _Release. CreateNewSurface is called for 
each complex sublevel surface(e.g. front+backbuffer if they are created via 
DDSC_COMPLEX), while IDirectDrawSurface::Release must be called only for the 
root surface(ie, the pointer returned from IDirectDraw::CreateSurface). That 
means you have to move the IDirectDrawInternal_Release into 
IDirectDrawSurfaceImpl_Destroy, otherwise there's a reference leak.

More information about the wine-devel mailing list