Store a bitmap of active hooks on the client side to try to avoid
server calls for hooks that are not set.
This commit is contained in:
parent
ea6ecf44ff
commit
63342353bc
|
@ -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;
|
||||
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 );
|
||||
}
|
||||
/* 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;
|
||||
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 );
|
||||
}
|
||||
/* 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 */
|
||||
|
||||
|
|
Loading…
Reference in New Issue