diff --git a/dlls/ddraw/tests/d3d.c b/dlls/ddraw/tests/d3d.c index 82fdedf29df..a8535a37cd2 100644 --- a/dlls/ddraw/tests/d3d.c +++ b/dlls/ddraw/tests/d3d.c @@ -3263,9 +3263,9 @@ static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM static void test_wndproc(void) { + LONG_PTR proc, ddraw_proc; IDirectDraw7 *ddraw7; WNDCLASSA wc = {0}; - LONG_PTR proc; HWND window; HRESULT hr; ULONG ref; @@ -3356,7 +3356,87 @@ static void test_wndproc(void) (LONG_PTR)test_proc, proc); /* The original window proc is only restored by ddraw if the current - * window proc matches the one ddraw set. */ + * window proc matches the one ddraw set. This also affects switching + * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */ + hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL); + if (FAILED(hr)) + { + skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr); + return; + } + + proc = GetWindowLongPtrA(window, GWLP_WNDPROC); + ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n", + (LONG_PTR)test_proc, proc); + + hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); + ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr); + if (FAILED(hr)) + { + IDirectDraw7_Release(ddraw7); + goto done; + } + + proc = GetWindowLongPtrA(window, GWLP_WNDPROC); + ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n", + (LONG_PTR)test_proc, proc); + ddraw_proc = proc; + + hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL); + ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr); + if (FAILED(hr)) + { + IDirectDraw7_Release(ddraw7); + goto done; + } + + proc = GetWindowLongPtrA(window, GWLP_WNDPROC); + ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n", + (LONG_PTR)test_proc, proc); + + hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); + ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr); + if (FAILED(hr)) + { + IDirectDraw7_Release(ddraw7); + goto done; + } + + proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA); + ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n", + (LONG_PTR)test_proc, proc); + + hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL); + ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr); + if (FAILED(hr)) + { + IDirectDraw7_Release(ddraw7); + goto done; + } + + proc = GetWindowLongPtrA(window, GWLP_WNDPROC); + ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n", + (LONG_PTR)DefWindowProcA, proc); + + hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); + ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr); + if (FAILED(hr)) + { + IDirectDraw7_Release(ddraw7); + goto done; + } + + proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc); + ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n", + (LONG_PTR)DefWindowProcA, proc); + + ref = IDirectDraw7_Release(ddraw7); + ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref); + + proc = GetWindowLongPtrA(window, GWLP_WNDPROC); + ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n", + (LONG_PTR)test_proc, proc); + hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL); if (FAILED(hr)) { diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c index 0e4470274d9..8cc2828db7e 100644 --- a/dlls/wined3d/wined3d_main.c +++ b/dlls/wined3d/wined3d_main.c @@ -467,35 +467,49 @@ BOOL wined3d_register_window(HWND window, IWineD3DDeviceImpl *device) void wined3d_unregister_window(HWND window) { - unsigned int i; + struct wined3d_wndproc *entry, *last; + LONG_PTR proc; wined3d_mutex_lock(); - for (i = 0; i < wndproc_table.count; ++i) + + if (!(entry = wined3d_find_wndproc(window))) { - if (wndproc_table.entries[i].window == window) + wined3d_mutex_unlock(); + ERR("Window %p is not registered with wined3d.\n", window); + return; + } + + if (entry->unicode) + { + proc = GetWindowLongPtrW(window, GWLP_WNDPROC); + if (proc != (LONG_PTR)wined3d_wndproc) { - struct wined3d_wndproc *entry = &wndproc_table.entries[i]; - struct wined3d_wndproc *last = &wndproc_table.entries[--wndproc_table.count]; - - if (entry->unicode) - { - if (GetWindowLongPtrW(window, GWLP_WNDPROC) == (LONG_PTR)wined3d_wndproc) - SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)entry->proc); - } - else - { - if (GetWindowLongPtrA(window, GWLP_WNDPROC) == (LONG_PTR)wined3d_wndproc) - SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)entry->proc); - } - if (entry != last) *entry = *last; wined3d_mutex_unlock(); - + WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n", + window, proc, wined3d_wndproc); return; } - } - wined3d_mutex_unlock(); - ERR("Window %p is not registered with wined3d.\n", window); + SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)entry->proc); + } + else + { + proc = GetWindowLongPtrA(window, GWLP_WNDPROC); + if (proc != (LONG_PTR)wined3d_wndproc) + { + wined3d_mutex_unlock(); + WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n", + window, proc, wined3d_wndproc); + return; + } + + SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)entry->proc); + } + + last = &wndproc_table.entries[--wndproc_table.count]; + if (entry != last) *entry = *last; + + wined3d_mutex_unlock(); } /* At process attach */