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