user32: Limit number of hooks called recursively.
This commit is contained in:
parent
ae6efa469b
commit
4bcb4881ae
|
@ -413,7 +413,19 @@ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARA
|
||||||
}
|
}
|
||||||
else if (info->proc)
|
else if (info->proc)
|
||||||
{
|
{
|
||||||
|
struct user_thread_info *thread_info = get_user_thread_info();
|
||||||
HMODULE free_module = 0;
|
HMODULE free_module = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Windows protects from stack overflow in recursive hook calls. Different Windows
|
||||||
|
* allow different depths.
|
||||||
|
*/
|
||||||
|
if (thread_info->hook_call_depth >= 25)
|
||||||
|
{
|
||||||
|
WARN("Too many hooks called recursively, skipping call.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
TRACE( "calling hook %p %s code %x wp %lx lp %lx module %s\n",
|
TRACE( "calling hook %p %s code %x wp %lx lp %lx module %s\n",
|
||||||
info->proc, hook_names[info->id-WH_MINHOOK], code, wparam,
|
info->proc, hook_names[info->id-WH_MINHOOK], code, wparam,
|
||||||
lparam, debugstr_w(info->module) );
|
lparam, debugstr_w(info->module) );
|
||||||
|
@ -421,16 +433,17 @@ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARA
|
||||||
if (!info->module[0] ||
|
if (!info->module[0] ||
|
||||||
(info->proc = get_hook_proc( info->proc, info->module, &free_module )) != NULL)
|
(info->proc = get_hook_proc( info->proc, info->module, &free_module )) != NULL)
|
||||||
{
|
{
|
||||||
struct user_thread_info *thread_info = get_user_thread_info();
|
|
||||||
HHOOK prev = thread_info->hook;
|
HHOOK prev = thread_info->hook;
|
||||||
BOOL prev_unicode = thread_info->hook_unicode;
|
BOOL prev_unicode = thread_info->hook_unicode;
|
||||||
|
|
||||||
thread_info->hook = info->handle;
|
thread_info->hook = info->handle;
|
||||||
thread_info->hook_unicode = info->next_unicode;
|
thread_info->hook_unicode = info->next_unicode;
|
||||||
|
thread_info->hook_call_depth++;
|
||||||
ret = call_hook_proc( info->proc, info->id, code, wparam, lparam,
|
ret = call_hook_proc( info->proc, info->id, code, wparam, lparam,
|
||||||
info->prev_unicode, info->next_unicode );
|
info->prev_unicode, info->next_unicode );
|
||||||
thread_info->hook = prev;
|
thread_info->hook = prev;
|
||||||
thread_info->hook_unicode = prev_unicode;
|
thread_info->hook_unicode = prev_unicode;
|
||||||
|
thread_info->hook_call_depth--;
|
||||||
|
|
||||||
if (free_module) FreeLibrary(free_module);
|
if (free_module) FreeLibrary(free_module);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9182,6 +9182,54 @@ todo_wine {
|
||||||
"unexpected error %d\n", GetLastError());
|
"unexpected error %d\n", GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HWND hook_hwnd;
|
||||||
|
static HHOOK recursive_hook;
|
||||||
|
static int hook_depth, max_hook_depth;
|
||||||
|
|
||||||
|
static LRESULT WINAPI rec_get_message_hook(int code, WPARAM w, LPARAM l)
|
||||||
|
{
|
||||||
|
LRESULT res;
|
||||||
|
MSG msg;
|
||||||
|
BOOL b;
|
||||||
|
|
||||||
|
hook_depth++;
|
||||||
|
if(hook_depth > max_hook_depth)
|
||||||
|
max_hook_depth = hook_depth;
|
||||||
|
|
||||||
|
b = PeekMessageW(&msg, hook_hwnd, 0, 0, PM_NOREMOVE);
|
||||||
|
ok(b, "PeekMessage failed\n");
|
||||||
|
|
||||||
|
res = CallNextHookEx(recursive_hook, code, w, l);
|
||||||
|
|
||||||
|
hook_depth--;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_recursive_hook(void)
|
||||||
|
{
|
||||||
|
MSG msg;
|
||||||
|
BOOL b;
|
||||||
|
|
||||||
|
hook_hwnd = CreateWindowA("Static", NULL, WS_POPUP, 0, 0, 200, 60, NULL, NULL, NULL, NULL);
|
||||||
|
ok(hook_hwnd != NULL, "CreateWindow failed\n");
|
||||||
|
|
||||||
|
recursive_hook = SetWindowsHookExW(WH_GETMESSAGE, rec_get_message_hook, NULL, GetCurrentThreadId());
|
||||||
|
ok(recursive_hook != NULL, "SetWindowsHookEx failed\n");
|
||||||
|
|
||||||
|
PostMessageW(hook_hwnd, WM_USER, 0, 0);
|
||||||
|
PostMessageW(hook_hwnd, WM_USER+1, 0, 0);
|
||||||
|
|
||||||
|
hook_depth = 0;
|
||||||
|
GetMessageW(&msg, hook_hwnd, 0, 0);
|
||||||
|
ok(15 < max_hook_depth && max_hook_depth < 45, "max_hook_depth = %d\n", max_hook_depth);
|
||||||
|
trace("max_hook_depth = %d\n", max_hook_depth);
|
||||||
|
|
||||||
|
b = UnhookWindowsHookEx(recursive_hook);
|
||||||
|
ok(b, "UnhokWindowsHookEx failed\n");
|
||||||
|
|
||||||
|
DestroyWindow(hook_hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct message ScrollWindowPaint1[] = {
|
static const struct message ScrollWindowPaint1[] = {
|
||||||
{ WM_PAINT, sent },
|
{ WM_PAINT, sent },
|
||||||
{ WM_ERASEBKGND, sent|beginpaint },
|
{ WM_ERASEBKGND, sent|beginpaint },
|
||||||
|
@ -14946,7 +14994,11 @@ START_TEST(msg)
|
||||||
test_timers();
|
test_timers();
|
||||||
test_timers_no_wnd();
|
test_timers_no_wnd();
|
||||||
test_timers_exceptions();
|
test_timers_exceptions();
|
||||||
if (hCBT_hook) test_set_hook();
|
if (hCBT_hook)
|
||||||
|
{
|
||||||
|
test_set_hook();
|
||||||
|
test_recursive_hook();
|
||||||
|
}
|
||||||
test_DestroyWindow();
|
test_DestroyWindow();
|
||||||
test_DispatchMessage();
|
test_DispatchMessage();
|
||||||
test_SendMessageTimeout();
|
test_SendMessageTimeout();
|
||||||
|
|
|
@ -175,6 +175,7 @@ struct user_thread_info
|
||||||
DWORD changed_mask; /* Current queue changed mask */
|
DWORD changed_mask; /* Current queue changed mask */
|
||||||
WORD recursion_count; /* SendMessage recursion counter */
|
WORD recursion_count; /* SendMessage recursion counter */
|
||||||
WORD message_count; /* Get/PeekMessage loop counter */
|
WORD message_count; /* Get/PeekMessage loop counter */
|
||||||
|
WORD hook_call_depth; /* Number of recursively called hook procs */
|
||||||
BOOL hook_unicode; /* Is current hook unicode? */
|
BOOL hook_unicode; /* Is current hook unicode? */
|
||||||
HHOOK hook; /* Current hook */
|
HHOOK hook; /* Current hook */
|
||||||
struct received_message_info *receive_info; /* Message being currently received */
|
struct received_message_info *receive_info; /* Message being currently received */
|
||||||
|
|
Loading…
Reference in New Issue