diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index cec78214a37..bd13d563f57 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -3007,6 +3007,7 @@ IDirectDrawImpl_CreatePalette(IDirectDraw7 *iface, } IDirectDraw7_AddRef(iface); + object->ifaceToRelease = (IUnknown *) iface; *Palette = ICOM_INTERFACE(object, IDirectDrawPalette); return DD_OK; } diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 74bed0e4b75..5cf93129158 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -393,6 +393,7 @@ struct IDirectDrawPaletteImpl /* IDirectDrawPalette fields */ IDirectDrawImpl *ddraw_owner; + IUnknown *ifaceToRelease; }; const IDirectDrawPaletteVtbl IDirectDrawPalette_Vtbl; diff --git a/dlls/ddraw/ddraw_thunks.c b/dlls/ddraw/ddraw_thunks.c index 7ccc65d79f7..c0b0641b7fe 100644 --- a/dlls/ddraw/ddraw_thunks.c +++ b/dlls/ddraw/ddraw_thunks.c @@ -236,10 +236,13 @@ IDirectDrawImpl_CreatePalette(LPDIRECTDRAW This, DWORD dwFlags, dwFlags, pEntries, ppPalette, pUnkOuter); if(SUCCEEDED(hr) && *ppPalette) { + IDirectDrawPaletteImpl *impl = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette, *ppPalette); IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl, IDirectDraw, IDirectDraw7, This)); + impl->ifaceToRelease = NULL; + } return hr; } @@ -251,18 +254,21 @@ IDirectDraw2Impl_CreatePalette(LPDIRECTDRAW2 This, DWORD dwFlags, IUnknown *pUnkOuter) { HRESULT hr; - return IDirectDraw7_CreatePalette(COM_INTERFACE_CAST(IDirectDrawImpl, + hr = IDirectDraw7_CreatePalette(COM_INTERFACE_CAST(IDirectDrawImpl, IDirectDraw2, IDirectDraw7, This), dwFlags, pEntries, ppPalette, pUnkOuter); if(SUCCEEDED(hr) && *ppPalette) { + IDirectDrawPaletteImpl *impl = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette, *ppPalette); IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl, - IDirectDraw, + IDirectDraw2, IDirectDraw7, This)); + impl->ifaceToRelease = NULL; } + return hr; } static HRESULT WINAPI @@ -272,18 +278,22 @@ IDirectDraw4Impl_CreatePalette(LPDIRECTDRAW4 This, DWORD dwFlags, IUnknown *pUnkOuter) { HRESULT hr; - return IDirectDraw7_CreatePalette(COM_INTERFACE_CAST(IDirectDrawImpl, + hr = IDirectDraw7_CreatePalette(COM_INTERFACE_CAST(IDirectDrawImpl, IDirectDraw4, IDirectDraw7, This), dwFlags, pEntries, ppPalette, pUnkOuter); if(SUCCEEDED(hr) && *ppPalette) { + IDirectDrawPaletteImpl *impl = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette, *ppPalette); IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl, - IDirectDraw, + IDirectDraw4, IDirectDraw7, This)); + IDirectDraw4_AddRef(This); + impl->ifaceToRelease = (IUnknown *) This; } + return hr; } static HRESULT WINAPI diff --git a/dlls/ddraw/palette.c b/dlls/ddraw/palette.c index 97a9ef40b8f..03bdb3ad452 100644 --- a/dlls/ddraw/palette.c +++ b/dlls/ddraw/palette.c @@ -21,6 +21,8 @@ #include "winerror.h" #include "wine/debug.h" +#define COBJMACROS + #include #include @@ -104,7 +106,10 @@ IDirectDrawPaletteImpl_Release(IDirectDrawPalette *iface) if (ref == 0) { IWineD3DPalette_Release(This->wineD3DPalette); - IDirectDraw7_Release(ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7)); + if(This->ifaceToRelease) + { + IUnknown_Release(This->ifaceToRelease); + } HeapFree(GetProcessHeap(), 0, This); } diff --git a/dlls/ddraw/tests/refcount.c b/dlls/ddraw/tests/refcount.c index 6e27665b974..9dceda6bd89 100644 --- a/dlls/ddraw/tests/refcount.c +++ b/dlls/ddraw/tests/refcount.c @@ -47,32 +47,42 @@ static void test_ddraw_objects(void) { HRESULT hr; unsigned long ref; - IDirectDraw7 *DDraw; + IDirectDraw7 *DDraw7; + IDirectDraw4 *DDraw4; + IDirectDraw4 *DDraw2; + IDirectDraw4 *DDraw1; IDirectDrawPalette *palette; IDirectDrawSurface7 *surface; PALETTEENTRY Table[256]; DDSURFACEDESC2 ddsd; - hr = pDirectDrawCreateEx(NULL, (void **) &DDraw, &IID_IDirectDraw7, NULL); + hr = pDirectDrawCreateEx(NULL, (void **) &DDraw7, &IID_IDirectDraw7, NULL); ok(hr == DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %lx\n", hr); - if(!DDraw) + if(!DDraw7) { trace("Couldn't create DDraw interface, skipping tests\n"); return; } - ref = getRefcount( (IUnknown *) DDraw); + hr = IDirectDraw7_QueryInterface(DDraw7, &IID_IDirectDraw4, (void **) &DDraw4); + ok(hr == DD_OK, "IDirectDraw7_QueryInterface returned %08lx\n", hr); + hr = IDirectDraw7_QueryInterface(DDraw7, &IID_IDirectDraw2, (void **) &DDraw2); + ok(hr == DD_OK, "IDirectDraw7_QueryInterface returned %08lx\n", hr); + hr = IDirectDraw7_QueryInterface(DDraw7, &IID_IDirectDraw, (void **) &DDraw1); + ok(hr == DD_OK, "IDirectDraw7_QueryInterface returned %08lx\n", hr); + + ref = getRefcount( (IUnknown *) DDraw7); ok(ref == 1, "Got refcount %ld, expected 1\n", ref); /* Fails without a cooplevel */ - hr = IDirectDraw7_CreatePalette(DDraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL); + hr = IDirectDraw7_CreatePalette(DDraw7, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL); ok(hr == DDERR_NOCOOPERATIVELEVELSET, "CreatePalette returned %08lx\n", hr); /* This check is before the cooplevel check */ - hr = IDirectDraw7_CreatePalette(DDraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, (void *) 0xdeadbeef); + hr = IDirectDraw7_CreatePalette(DDraw7, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, (void *) 0xdeadbeef); ok(hr == CLASS_E_NOAGGREGATION, "CreatePalette returned %08lx\n", hr); - hr = IDirectDraw7_SetCooperativeLevel(DDraw, 0, DDSCL_NORMAL); + hr = IDirectDraw7_SetCooperativeLevel(DDraw7, 0, DDSCL_NORMAL); ok(hr == DD_OK, "SetCooperativeLevel failed with %08lx\n", hr); memset(&ddsd, 0, sizeof(ddsd)); @@ -85,22 +95,22 @@ static void test_ddraw_objects(void) U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB; U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8; - hr = IDirectDraw7_CreateSurface(DDraw, &ddsd, &surface, NULL); + hr = IDirectDraw7_CreateSurface(DDraw7, &ddsd, &surface, NULL); ok(hr == DD_OK, "CreateSurface failed with %08lx\n", hr); /* DDraw refcount increased by 1 */ - ref = getRefcount( (IUnknown *) DDraw); + ref = getRefcount( (IUnknown *) DDraw7); ok(ref == 2, "Got refcount %ld, expected 2\n", ref); /* Surface refcount starts with 1 */ ref = getRefcount( (IUnknown *) surface); ok(ref == 1, "Got refcount %ld, expected 1\n", ref); - hr = IDirectDraw7_CreatePalette(DDraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL); + hr = IDirectDraw7_CreatePalette(DDraw7, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL); ok(hr == DD_OK, "CreatePalette returned %08lx\n", hr); /* DDraw refcount increased by 1 */ - ref = getRefcount( (IUnknown *) DDraw); + ref = getRefcount( (IUnknown *) DDraw7); ok(ref == 3, "Got refcount %ld, expected 3\n", ref); /* Palette starts with 1 */ @@ -119,7 +129,7 @@ static void test_ddraw_objects(void) IDirectDrawSurface7_Release(surface); /* Incresed before - decrease now */ - ref = getRefcount( (IUnknown *) DDraw); + ref = getRefcount( (IUnknown *) DDraw7); ok(ref == 2, "Got refcount %ld, expected 2\n", ref); /* Releasing the surface detaches the palette */ @@ -129,10 +139,34 @@ static void test_ddraw_objects(void) IDirectDrawPalette_Release(palette); /* Incresed before - decrease now */ - ref = getRefcount( (IUnknown *) DDraw); + ref = getRefcount( (IUnknown *) DDraw7); ok(ref == 1, "Got refcount %ld, expected 1\n", ref); - IDirectDraw7_Release(DDraw); + /* Not all interfaces are AddRefed when a palette is created */ + hr = IDirectDraw4_CreatePalette(DDraw4, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL); + ok(hr == DD_OK, "CreatePalette returned %08lx\n", hr); + ref = getRefcount( (IUnknown *) DDraw4); + ok(ref == 2, "Got refcount %ld, expected 2\n", ref); + IDirectDrawPalette_Release(palette); + + /* No addref here */ + hr = IDirectDraw2_CreatePalette(DDraw2, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL); + ok(hr == DD_OK, "CreatePalette returned %08lx\n", hr); + ref = getRefcount( (IUnknown *) DDraw2); + ok(ref == 1, "Got refcount %ld, expected 1\n", ref); + IDirectDrawPalette_Release(palette); + + /* No addref here */ + hr = IDirectDraw_CreatePalette(DDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL); + ok(hr == DD_OK, "CreatePalette returned %08lx\n", hr); + ref = getRefcount( (IUnknown *) DDraw1); + ok(ref == 1, "Got refcount %ld, expected 1\n", ref); + IDirectDrawPalette_Release(palette); + + IDirectDraw7_Release(DDraw7); + IDirectDraw4_Release(DDraw4); + IDirectDraw2_Release(DDraw2); + IDirectDraw_Release(DDraw1); } static void test_iface_refcnt(void)