/*********************************************************************** * call_hook * * Call hook either in current thread or send message to the destination * thread. */ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARAM lparam ) { DWORD_PTR ret = 0; if (info->tid) { struct hook_extra_info h_extra; h_extra.handle = info->handle; h_extra.lparam = lparam; TRACE( "calling hook in thread %04x %s code %x wp %lx lp %lx\n", info->tid, hook_names[info->id-WH_MINHOOK], code, wparam, lparam ); switch(info->id) { case WH_KEYBOARD_LL: MSG_SendInternalMessageTimeout( info->pid, info->tid, WM_WINE_KEYBOARD_LL_HOOK, wparam, (LPARAM)&h_extra, SMTO_ABORTIFHUNG, get_ll_hook_timeout(), &ret ); break; case WH_MOUSE_LL: MSG_SendInternalMessageTimeout( info->pid, info->tid, WM_WINE_MOUSE_LL_HOOK, wparam, (LPARAM)&h_extra, SMTO_ABORTIFHUNG, get_ll_hook_timeout(), &ret ); break; default: ERR("Unknown hook id %d\n", info->id); assert(0); break; } } else if (info->proc) { TRACE( "calling hook %p %s code %x wp %lx lp %lx module %s\n", info->proc, hook_names[info->id-WH_MINHOOK], code, wparam, lparam, debugstr_w(info->module) ); if (!info->module[0] || (info->proc = get_hook_proc( info->proc, info->module )) != NULL) { struct user_thread_info *thread_info = get_user_thread_info(); HHOOK prev = thread_info->hook; BOOL prev_unicode = thread_info->hook_unicode; thread_info->hook = info->handle; thread_info->hook_unicode = info->next_unicode; ret = call_hook_proc( info->proc, info->id, code, wparam, lparam, info->prev_unicode, info->next_unicode ); thread_info->hook = prev; thread_info->hook_unicode = prev_unicode; } } if (info->id == WH_KEYBOARD_LL || info->id == WH_MOUSE_LL) get_user_thread_info()->key_state_time = 0; /* force refreshing the key state cache */ return ret; }
/*********************************************************************** * call_hook * * Call hook either in current thread or send message to the destination * thread. */ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARAM lparam ) { DWORD_PTR ret = 0; if (info->tid) { struct hook_extra_info h_extra; h_extra.handle = info->handle; h_extra.lparam = lparam; TRACE( "calling hook in thread %04x %s code %x wp %lx lp %lx\n", info->tid, hook_names[info->id-WH_MINHOOK], code, wparam, lparam ); switch(info->id) { case WH_KEYBOARD_LL: MSG_SendInternalMessageTimeout( info->pid, info->tid, WM_WINE_KEYBOARD_LL_HOOK, wparam, (LPARAM)&h_extra, SMTO_ABORTIFHUNG, get_ll_hook_timeout(), &ret ); break; case WH_MOUSE_LL: MSG_SendInternalMessageTimeout( info->pid, info->tid, WM_WINE_MOUSE_LL_HOOK, wparam, (LPARAM)&h_extra, SMTO_ABORTIFHUNG, get_ll_hook_timeout(), &ret ); break; default: ERR("Unknown hook id %d\n", info->id); assert(0); break; } } else if (info->proc) { struct user_thread_info *thread_info = get_user_thread_info(); 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", info->proc, hook_names[info->id-WH_MINHOOK], code, wparam, lparam, debugstr_w(info->module) ); if (!info->module[0] || (info->proc = get_hook_proc( info->proc, info->module, &free_module )) != NULL) { HHOOK prev = thread_info->hook; BOOL prev_unicode = thread_info->hook_unicode; thread_info->hook = info->handle; thread_info->hook_unicode = info->next_unicode; thread_info->hook_call_depth++; ret = call_hook_proc( info->proc, info->id, code, wparam, lparam, info->prev_unicode, info->next_unicode ); thread_info->hook = prev; thread_info->hook_unicode = prev_unicode; thread_info->hook_call_depth--; if (free_module) FreeLibrary(free_module); } } if (info->id == WH_KEYBOARD_LL || info->id == WH_MOUSE_LL) interlocked_xchg_add( &global_key_state_counter, 1 ); /* force refreshing the key state cache */ return ret; }