Commit 63342353 authored by Alexandre Julliard's avatar Alexandre Julliard

Store a bitmap of active hooks on the client side to try to avoid

server calls for hooks that are not set.
parent ea6ecf44
......@@ -189,7 +189,11 @@ static HHOOK set_windows_hook( INT id, HOOKPROC proc, HINSTANCE inst, DWORD tid,
}
else req->proc = proc;
if (!wine_server_call_err( req )) handle = reply->handle;
if (!wine_server_call_err( req ))
{
handle = reply->handle;
get_user_thread_info()->active_hooks = reply->active_hooks;
}
}
SERVER_END_REQ;
......@@ -333,6 +337,12 @@ LRESULT HOOK_CallHooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL uni
USER_CheckNotLock();
if (!HOOK_IsHooked( id ))
{
TRACE( "skipping hook %s mask %x\n", hook_names[id-WH_MINHOOK], thread_info->active_hooks );
return 0;
}
SERVER_START_REQ( start_hook_chain )
{
req->id = id;
......@@ -346,6 +356,7 @@ LRESULT HOOK_CallHooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL uni
pid = reply->pid;
tid = reply->tid;
unicode_hook = reply->unicode;
thread_info->active_hooks = reply->active_hooks;
}
}
SERVER_END_REQ;
......@@ -402,7 +413,10 @@ LRESULT HOOK_CallHooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL uni
*/
BOOL HOOK_IsHooked( INT id )
{
return TRUE; /* FIXME */
struct user_thread_info *thread_info = get_user_thread_info();
if (!thread_info->active_hooks) return TRUE;
return (thread_info->active_hooks & (1 << (id - WH_MINHOOK))) != 0;
}
......@@ -456,6 +470,7 @@ BOOL WINAPI UnhookWindowsHook( INT id, HOOKPROC proc )
req->id = id;
req->proc = proc;
ret = !wine_server_call_err( req );
if (ret) get_user_thread_info()->active_hooks = reply->active_hooks;
}
SERVER_END_REQ;
if (!ret && GetLastError() == ERROR_INVALID_HANDLE) SetLastError( ERROR_INVALID_HOOK_HANDLE );
......@@ -478,6 +493,7 @@ BOOL WINAPI UnhookWindowsHookEx( HHOOK hhook )
req->handle = hhook;
req->id = 0;
ret = !wine_server_call_err( req );
if (ret) get_user_thread_info()->active_hooks = reply->active_hooks;
}
SERVER_END_REQ;
if (!ret && GetLastError() == ERROR_INVALID_HANDLE) SetLastError( ERROR_INVALID_HOOK_HANDLE );
......@@ -643,7 +659,11 @@ HWINEVENTHOOK WINAPI SetWinEventHook(DWORD event_min, DWORD event_max,
}
else req->proc = proc;
if (!wine_server_call_err( req )) handle = reply->handle;
if (!wine_server_call_err( req ))
{
handle = reply->handle;
get_user_thread_info()->active_hooks = reply->active_hooks;
}
}
SERVER_END_REQ;
......@@ -675,6 +695,7 @@ BOOL WINAPI UnhookWinEvent(HWINEVENTHOOK hEventHook)
req->handle = hEventHook;
req->id = WH_WINEVENT;
ret = !wine_server_call_err( req );
if (ret) get_user_thread_info()->active_hooks = reply->active_hooks;
}
SERVER_END_REQ;
return ret;
......@@ -683,8 +704,15 @@ BOOL WINAPI UnhookWinEvent(HWINEVENTHOOK hEventHook)
inline static BOOL find_first_hook(DWORD id, DWORD event, HWND hwnd, LONG object_id,
LONG child_id, struct hook_info *info)
{
struct user_thread_info *thread_info = get_user_thread_info();
BOOL ret;
if (!HOOK_IsHooked( id ))
{
TRACE( "skipping hook %s mask %x\n", hook_names[id-WH_MINHOOK], thread_info->active_hooks );
return FALSE;
}
SERVER_START_REQ( start_hook_chain )
{
req->id = id;
......@@ -700,6 +728,7 @@ inline static BOOL find_first_hook(DWORD id, DWORD event, HWND hwnd, LONG object
info->handle = reply->handle;
info->proc = reply->proc;
info->tid = reply->tid;
thread_info->active_hooks = reply->active_hooks;
}
}
SERVER_END_REQ;
......
......@@ -1942,6 +1942,7 @@ static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags
info.hook_proc = reply->hook_proc;
hw_id = reply->hw_id;
extra_info = reply->info;
thread_info->active_hooks = reply->active_hooks;
}
else
{
......
......@@ -138,7 +138,8 @@ struct user_thread_info
DWORD GetMessageExtraInfoVal; /* 1c Value for GetMessageExtraInfo */
HCURSOR cursor; /* 20 Current cursor */
INT cursor_count; /* 24 Cursor show count */
/* 28-7c Available for more data */
UINT active_hooks; /* 28 Bitmap of active hooks */
/* 2c-7c Available for more data */
};
static inline struct user_thread_info *get_user_thread_info(void)
......
......@@ -2203,6 +2203,7 @@ struct get_message_reply
unsigned int time;
unsigned int info;
unsigned int hw_id;
unsigned int active_hooks;
size_t total;
/* VARARG(data,bytes); */
};
......@@ -3044,6 +3045,7 @@ struct set_hook_reply
{
struct reply_header __header;
user_handle_t handle;
unsigned int active_hooks;
};
......@@ -3058,6 +3060,7 @@ struct remove_hook_request
struct remove_hook_reply
{
struct reply_header __header;
unsigned int active_hooks;
};
......@@ -3079,6 +3082,7 @@ struct start_hook_chain_reply
thread_id_t tid;
void* proc;
int unicode;
unsigned int active_hooks;
/* VARARG(module,unicode_str); */
};
......@@ -3954,6 +3958,6 @@ union generic_reply
struct set_mailslot_info_reply set_mailslot_info_reply;
};
#define SERVER_PROTOCOL_VERSION 173
#define SERVER_PROTOCOL_VERSION 174
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -172,6 +172,19 @@ inline static struct hook *get_first_hook( struct hook_table *table, int index )
return elem ? HOOK_ENTRY( elem ) : NULL;
}
/* check if a given hook should run in the current thread */
inline static int run_hook_in_current_thread( struct hook *hook )
{
if ((!hook->process || hook->process == current->process) &&
(!(hook->flags & WINEVENT_SKIPOWNPROCESS) || hook->process != current->process))
{
if ((!hook->thread || hook->thread == current) &&
(!(hook->flags & WINEVENT_SKIPOWNTHREAD) || hook->thread != current))
return 1;
}
return 0;
}
/* find the first non-deleted hook in the chain */
inline static struct hook *get_first_valid_hook( struct hook_table *table, int index,
int event, user_handle_t win,
......@@ -181,22 +194,17 @@ inline static struct hook *get_first_valid_hook( struct hook_table *table, int i
while (hook)
{
if ((!hook->process || hook->process == current->process) &&
(!(hook->flags & WINEVENT_SKIPOWNPROCESS) || hook->process != current->process))
if (hook->proc && run_hook_in_current_thread( hook ))
{
if ((!hook->thread || hook->thread == current) &&
(!(hook->flags & WINEVENT_SKIPOWNTHREAD) || hook->thread != current))
if (event >= hook->event_min && event <= hook->event_max)
{
if (hook->proc && event >= hook->event_min && event <= hook->event_max)
{
if (hook->flags & WINEVENT_INCONTEXT) return hook;
/* only winevent hooks may be out of context */
assert(hook->index + WH_MINHOOK == WH_WINEVENT);
post_win_event( hook->owner, event, win, object_id, child_id,
hook->proc, hook->module, hook->module_size,
hook->handle );
}
if (hook->flags & WINEVENT_INCONTEXT) return hook;
/* only winevent hooks may be out of context */
assert(hook->index + WH_MINHOOK == WH_WINEVENT);
post_win_event( hook->owner, event, win, object_id, child_id,
hook->proc, hook->module, hook->module_size,
hook->handle );
}
}
hook = HOOK_ENTRY( list_next( &table->hooks[index], &hook->chain ) );
......@@ -213,22 +221,17 @@ static struct hook *get_next_hook( struct hook *hook, int event, user_handle_t w
while ((hook = HOOK_ENTRY( list_next( &table->hooks[index], &hook->chain ) )))
{
if ((!hook->process || hook->process == current->process) &&
(!(hook->flags & WINEVENT_SKIPOWNPROCESS) || hook->process != current->process))
if (hook->proc && run_hook_in_current_thread( hook ))
{
if ((!hook->thread || hook->thread == current) &&
(!(hook->flags & WINEVENT_SKIPOWNTHREAD) || hook->thread != current))
if (event >= hook->event_min && event <= hook->event_max)
{
if (hook->proc && event >= hook->event_min && event <= hook->event_max)
{
if (hook->flags & WINEVENT_INCONTEXT) return hook;
/* only winevent hooks may be out of context */
assert(hook->index + WH_MINHOOK == WH_WINEVENT);
post_win_event( hook->owner, event, win, object_id, child_id,
hook->proc, hook->module, hook->module_size,
hook->handle );
}
if (hook->flags & WINEVENT_INCONTEXT) return hook;
/* only winevent hooks may be out of context */
assert(hook->index + WH_MINHOOK == WH_WINEVENT);
post_win_event( hook->owner, event, win, object_id, child_id,
hook->proc, hook->module, hook->module_size,
hook->handle );
}
}
}
......@@ -314,6 +317,35 @@ void remove_thread_hooks( struct thread *thread )
}
}
/* get a bitmap of active hooks in a hook table */
static int is_hook_active( struct hook_table *table, int index )
{
struct hook *hook = get_first_hook( table, index );
while (hook)
{
if (hook->proc && run_hook_in_current_thread( hook )) return 1;
hook = HOOK_ENTRY( list_next( &table->hooks[index], &hook->chain ) );
}
return 0;
}
/* get a bitmap of all active hooks for the current thread */
unsigned int get_active_hooks(void)
{
struct hook_table *table = get_queue_hooks( current );
unsigned int ret = 1 << 31; /* set high bit to indicate that the bitmap is valid */
int id;
for (id = WH_MINHOOK; id <= WH_WINEVENT; id++)
{
if ((table && is_hook_active( table, id - WH_MINHOOK )) ||
(global_hooks && is_hook_active( global_hooks, id - WH_MINHOOK )))
ret |= 1 << (id - WH_MINHOOK);
}
return ret;
}
/* set a window hook */
DECL_HANDLER(set_hook)
{
......@@ -388,6 +420,7 @@ DECL_HANDLER(set_hook)
hook->module = module;
hook->module_size = module_size;
reply->handle = hook->handle;
reply->active_hooks = get_active_hooks();
}
else if (module) free( module );
......@@ -423,6 +456,7 @@ DECL_HANDLER(remove_hook)
}
}
remove_hook( hook );
reply->active_hooks = get_active_hooks();
}
......@@ -438,11 +472,15 @@ DECL_HANDLER(start_hook_chain)
return;
}
if (!table || !(hook = get_first_valid_hook( table, req->id - WH_MINHOOK, req->event, req->window, req->object_id, req->child_id )))
reply->active_hooks = get_active_hooks();
if (!table || !(hook = get_first_valid_hook( table, req->id - WH_MINHOOK, req->event,
req->window, req->object_id, req->child_id )))
{
/* try global table */
if (!(table = global_hooks) ||
!(hook = get_first_valid_hook( global_hooks, req->id - WH_MINHOOK, req->event, req->window, req->object_id, req->child_id )))
!(hook = get_first_valid_hook( global_hooks, req->id - WH_MINHOOK, req->event,
req->window, req->object_id, req->child_id )))
return; /* no hook set */
}
......
......@@ -1564,6 +1564,7 @@ enum message_type
unsigned int time; /* message time */
unsigned int info; /* extra info (callback argument for MSG_CALLBACK_RESULT) */
unsigned int hw_id; /* id if hardware message */
unsigned int active_hooks; /* active hooks bitmap */
size_t total; /* total size of extra data */
VARARG(data,bytes); /* message data for sent messages */
@END
......@@ -2129,6 +2130,7 @@ enum message_type
VARARG(module,unicode_str); /* module name */
@REPLY
user_handle_t handle; /* handle to the hook */
unsigned int active_hooks; /* active hooks bitmap */
@END
......@@ -2137,6 +2139,8 @@ enum message_type
user_handle_t handle; /* handle to the hook */
int id; /* id of the hook if handle is 0 */
void* proc; /* hook procedure if handle is 0 */
@REPLY
unsigned int active_hooks; /* active hooks bitmap */
@END
......@@ -2153,6 +2157,7 @@ enum message_type
thread_id_t tid; /* thread id for low-level keyboard/mouse hooks */
void* proc; /* hook procedure */
int unicode; /* is it a unicode hook? */
unsigned int active_hooks; /* active hooks bitmap */
VARARG(module,unicode_str); /* module name */
@END
......
......@@ -1572,6 +1572,8 @@ DECL_HANDLER(get_message)
struct msg_queue *queue = get_current_queue();
user_handle_t get_win = get_user_full_handle( req->get_win );
reply->active_hooks = get_active_hooks();
if (!queue) return;
gettimeofday( &queue->last_get_msg, NULL );
......
......@@ -1909,6 +1909,7 @@ static void dump_get_message_reply( const struct get_message_reply *req )
fprintf( stderr, " time=%08x,", req->time );
fprintf( stderr, " info=%08x,", req->info );
fprintf( stderr, " hw_id=%08x,", req->hw_id );
fprintf( stderr, " active_hooks=%08x,", req->active_hooks );
fprintf( stderr, " total=%d,", req->total );
fprintf( stderr, " data=" );
dump_varargs_bytes( cur_size );
......@@ -2542,7 +2543,8 @@ static void dump_set_hook_request( const struct set_hook_request *req )
static void dump_set_hook_reply( const struct set_hook_reply *req )
{
fprintf( stderr, " handle=%p", req->handle );
fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " active_hooks=%08x", req->active_hooks );
}
static void dump_remove_hook_request( const struct remove_hook_request *req )
......@@ -2552,6 +2554,11 @@ static void dump_remove_hook_request( const struct remove_hook_request *req )
fprintf( stderr, " proc=%p", req->proc );
}
static void dump_remove_hook_reply( const struct remove_hook_reply *req )
{
fprintf( stderr, " active_hooks=%08x", req->active_hooks );
}
static void dump_start_hook_chain_request( const struct start_hook_chain_request *req )
{
fprintf( stderr, " id=%d,", req->id );
......@@ -2568,6 +2575,7 @@ static void dump_start_hook_chain_reply( const struct start_hook_chain_reply *re
fprintf( stderr, " tid=%04x,", req->tid );
fprintf( stderr, " proc=%p,", req->proc );
fprintf( stderr, " unicode=%d,", req->unicode );
fprintf( stderr, " active_hooks=%08x,", req->active_hooks );
fprintf( stderr, " module=" );
dump_varargs_unicode_str( cur_size );
}
......@@ -3161,7 +3169,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_set_caret_window_reply,
(dump_func)dump_set_caret_info_reply,
(dump_func)dump_set_hook_reply,
(dump_func)0,
(dump_func)dump_remove_hook_reply,
(dump_func)dump_start_hook_chain_reply,
(dump_func)0,
(dump_func)dump_get_next_hook_reply,
......
......@@ -53,6 +53,7 @@ extern void cleanup_clipboard_thread( struct thread *thread );
extern void close_global_hooks(void);
extern void remove_thread_hooks( struct thread *thread );
extern unsigned int get_active_hooks(void);
/* queue functions */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment