wined3d: Don't unregister a window unless the window proc is what we expect it to be.
In particular, if we'd unregister a window when the application replaced our window proc, but still forwards to us, we'd create a loop when we register the same window again later.
This commit is contained in:
parent
9a1fddb0fd
commit
7a354177b3
|
@ -3263,9 +3263,9 @@ static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM
|
||||||
|
|
||||||
static void test_wndproc(void)
|
static void test_wndproc(void)
|
||||||
{
|
{
|
||||||
|
LONG_PTR proc, ddraw_proc;
|
||||||
IDirectDraw7 *ddraw7;
|
IDirectDraw7 *ddraw7;
|
||||||
WNDCLASSA wc = {0};
|
WNDCLASSA wc = {0};
|
||||||
LONG_PTR proc;
|
|
||||||
HWND window;
|
HWND window;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
ULONG ref;
|
ULONG ref;
|
||||||
|
@ -3356,7 +3356,87 @@ static void test_wndproc(void)
|
||||||
(LONG_PTR)test_proc, proc);
|
(LONG_PTR)test_proc, proc);
|
||||||
|
|
||||||
/* The original window proc is only restored by ddraw if the current
|
/* 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);
|
hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
|
|
|
@ -467,35 +467,49 @@ BOOL wined3d_register_window(HWND window, IWineD3DDeviceImpl *device)
|
||||||
|
|
||||||
void wined3d_unregister_window(HWND window)
|
void wined3d_unregister_window(HWND window)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
struct wined3d_wndproc *entry, *last;
|
||||||
|
LONG_PTR proc;
|
||||||
|
|
||||||
wined3d_mutex_lock();
|
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);
|
||||||
struct wined3d_wndproc *entry = &wndproc_table.entries[i];
|
return;
|
||||||
struct wined3d_wndproc *last = &wndproc_table.entries[--wndproc_table.count];
|
}
|
||||||
|
|
||||||
if (entry->unicode)
|
if (entry->unicode)
|
||||||
{
|
{
|
||||||
if (GetWindowLongPtrW(window, GWLP_WNDPROC) == (LONG_PTR)wined3d_wndproc)
|
proc = GetWindowLongPtrW(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;
|
||||||
|
}
|
||||||
|
|
||||||
SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
|
SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (GetWindowLongPtrA(window, GWLP_WNDPROC) == (LONG_PTR)wined3d_wndproc)
|
proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
|
||||||
SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
|
if (proc != (LONG_PTR)wined3d_wndproc)
|
||||||
}
|
{
|
||||||
if (entry != last) *entry = *last;
|
|
||||||
wined3d_mutex_unlock();
|
wined3d_mutex_unlock();
|
||||||
|
WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n",
|
||||||
|
window, proc, wined3d_wndproc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
wined3d_mutex_unlock();
|
|
||||||
|
|
||||||
ERR("Window %p is not registered with wined3d.\n", window);
|
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 */
|
/* At process attach */
|
||||||
|
|
Loading…
Reference in New Issue