[PATCH 8/8] ddraw/tests: Test destroying ddraw in WM_KILLFOCUS.

Stefan Dösinger stefan at codeweavers.com
Sat Oct 13 18:13:57 CDT 2018


Signed-off-by: Stefan Dösinger <stefan at codeweavers.com>

---

The ddraw object is actually freed and not kept alive by some hidden
refcount. I checked this by HeapAlloc'ing memory and zeroing it until
the address space is full. The memory killfocus_ddraw points to is
overwritten by this.
---
 dlls/ddraw/tests/ddraw1.c | 54 +++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw2.c | 54 +++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw4.c | 54 +++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw7.c | 54 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 216 insertions(+)

diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index aad7bbff1f4..1f93a97329e 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -11875,6 +11875,59 @@ static void test_find_device(void)
     IDirectDraw_Release(ddraw);
 }
 
+static IDirectDraw *killfocus_ddraw;
+static IDirectDrawSurface *killfocus_surface;
+
+static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
+{
+    ULONG ref;
+
+    if (message == WM_KILLFOCUS)
+    {
+        ref = IDirectDrawSurface_Release(killfocus_surface);
+        ok(!ref, "Unexpected surface refcount %u.\n", ref);
+        ref = IDirectDraw_Release(killfocus_ddraw);
+        ok(!ref, "Unexpected ddraw refcount %u.\n", ref);
+        killfocus_ddraw = NULL;
+    }
+
+    return DefWindowProcA(window, message, wparam, lparam);
+}
+
+static void test_killfocus(void)
+{
+    DDSURFACEDESC surface_desc;
+    HRESULT hr;
+    HWND window;
+    WNDCLASSA wc = {0};
+
+    wc.lpfnWndProc = killfocus_proc;
+    wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
+    ok(RegisterClassA(&wc), "Failed to register window class.\n");
+
+    window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
+            0, 0, 640, 480, 0, 0, 0, 0);
+
+    killfocus_ddraw = create_ddraw();
+    ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
+
+    hr = IDirectDraw_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+    hr = IDirectDraw_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    SetForegroundWindow(GetDesktopWindow());
+    ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
+
+    DestroyWindow(window);
+    UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
+}
+
 START_TEST(ddraw1)
 {
     DDDEVICEIDENTIFIER identifier;
@@ -11980,4 +12033,5 @@ START_TEST(ddraw1)
     test_execute_data();
     test_viewport();
     test_find_device();
+    test_killfocus();
 }
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index 29c3c845cb1..95cdf8bd82d 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -13157,6 +13157,59 @@ static void test_find_device(void)
     IDirectDraw2_Release(ddraw);
 }
 
+static IDirectDraw2 *killfocus_ddraw;
+static IDirectDrawSurface *killfocus_surface;
+
+static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
+{
+    ULONG ref;
+
+    if (message == WM_KILLFOCUS)
+    {
+        ref = IDirectDrawSurface_Release(killfocus_surface);
+        ok(!ref, "Unexpected surface refcount %u.\n", ref);
+        ref = IDirectDraw2_Release(killfocus_ddraw);
+        ok(!ref, "Unexpected ddraw refcount %u.\n", ref);
+        killfocus_ddraw = NULL;
+    }
+
+    return DefWindowProcA(window, message, wparam, lparam);
+}
+
+static void test_killfocus(void)
+{
+    DDSURFACEDESC surface_desc;
+    HRESULT hr;
+    HWND window;
+    WNDCLASSA wc = {0};
+
+    wc.lpfnWndProc = killfocus_proc;
+    wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
+    ok(RegisterClassA(&wc), "Failed to register window class.\n");
+
+    window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
+        0, 0, 640, 480, 0, 0, 0, 0);
+
+    killfocus_ddraw = create_ddraw();
+    ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
+
+    hr = IDirectDraw2_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+    hr = IDirectDraw_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    SetForegroundWindow(GetDesktopWindow());
+    ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
+
+    DestroyWindow(window);
+    UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
+}
+
 START_TEST(ddraw2)
 {
     DDDEVICEIDENTIFIER identifier;
@@ -13270,4 +13323,5 @@ START_TEST(ddraw2)
     test_enum_surfaces();
     test_viewport();
     test_find_device();
+    test_killfocus();
 }
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index 3aae42554f2..a62aaf0f30e 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -15265,6 +15265,59 @@ static void test_find_device(void)
     IDirectDraw4_Release(ddraw);
 }
 
+static IDirectDraw4 *killfocus_ddraw;
+static IDirectDrawSurface4 *killfocus_surface;
+
+static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
+{
+    ULONG ref;
+
+    if (message == WM_KILLFOCUS)
+    {
+        ref = IDirectDrawSurface4_Release(killfocus_surface);
+        ok(!ref, "Unexpected surface refcount %u.\n", ref);
+        ref = IDirectDraw4_Release(killfocus_ddraw);
+        ok(!ref, "Unexpected ddraw refcount %u.\n", ref);
+        killfocus_ddraw = NULL;
+    }
+
+    return DefWindowProcA(window, message, wparam, lparam);
+}
+
+static void test_killfocus(void)
+{
+    DDSURFACEDESC2 surface_desc;
+    HRESULT hr;
+    HWND window;
+    WNDCLASSA wc = {0};
+
+    wc.lpfnWndProc = killfocus_proc;
+    wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
+    ok(RegisterClassA(&wc), "Failed to register window class.\n");
+
+    window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
+        0, 0, 640, 480, 0, 0, 0, 0);
+
+    killfocus_ddraw = create_ddraw();
+    ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
+
+    hr = IDirectDraw4_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+    hr = IDirectDraw7_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    SetForegroundWindow(GetDesktopWindow());
+    ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
+
+    DestroyWindow(window);
+    UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
+}
+
 START_TEST(ddraw4)
 {
     DDDEVICEIDENTIFIER identifier;
@@ -15392,4 +15445,5 @@ START_TEST(ddraw4)
     test_enum_surfaces();
     test_viewport();
     test_find_device();
+    test_killfocus();
 }
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index 4691135186b..05151b06510 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -15035,6 +15035,59 @@ static void test_color_vertex(void)
     DestroyWindow(window);
 }
 
+static IDirectDraw7 *killfocus_ddraw;
+static IDirectDrawSurface7 *killfocus_surface;
+
+static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
+{
+    ULONG ref;
+
+    if (message == WM_KILLFOCUS)
+    {
+        ref = IDirectDrawSurface7_Release(killfocus_surface);
+        ok(!ref, "Unexpected surface refcount %u.\n", ref);
+        ref = IDirectDraw7_Release(killfocus_ddraw);
+        ok(!ref, "Unexpected ddraw refcount %u.\n", ref);
+        killfocus_ddraw = NULL;
+    }
+
+    return DefWindowProcA(window, message, wparam, lparam);
+}
+
+static void test_killfocus(void)
+{
+    DDSURFACEDESC2 surface_desc;
+    HRESULT hr;
+    HWND window;
+    WNDCLASSA wc = {0};
+
+    wc.lpfnWndProc = killfocus_proc;
+    wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
+    ok(RegisterClassA(&wc), "Failed to register window class.\n");
+
+    window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
+            0, 0, 640, 480, 0, 0, 0, 0);
+
+    killfocus_ddraw = create_ddraw();
+    ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
+
+    hr = IDirectDraw7_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+    hr = IDirectDraw7_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    SetForegroundWindow(GetDesktopWindow());
+    ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
+
+    DestroyWindow(window);
+    UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
+}
+
 START_TEST(ddraw7)
 {
     DDDEVICEIDENTIFIER2 identifier;
@@ -15173,4 +15226,5 @@ START_TEST(ddraw7)
     test_viewport();
     test_device_load();
     test_color_vertex();
+    test_killfocus();
 }
-- 
2.18.1




More information about the wine-devel mailing list