Store a bitmap of active hooks on the client side to try to avoid
server calls for hooks that are not set.
diff --git a/server/hook.c b/server/hook.c
index c228f98..125f346 100644
--- a/server/hook.c
+++ b/server/hook.c
@@ -172,6 +172,19 @@
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 @@
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 @@
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 @@
}
}
+/* 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 @@
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 @@
}
}
remove_hook( hook );
+ reply->active_hooks = get_active_hooks();
}
@@ -438,11 +472,15 @@
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 */
}
diff --git a/server/protocol.def b/server/protocol.def
index c21c8f5..6b07874 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1564,6 +1564,7 @@
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 @@
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 @@
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 @@
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
diff --git a/server/queue.c b/server/queue.c
index a0617a1..bdce76a 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1572,6 +1572,8 @@
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 );
diff --git a/server/trace.c b/server/trace.c
index 65ee3e9..cd05668 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1909,6 +1909,7 @@
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_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 @@
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 @@
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 @@
(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,
diff --git a/server/user.h b/server/user.h
index 36fd880..0f66a4d 100644
--- a/server/user.h
+++ b/server/user.h
@@ -53,6 +53,7 @@
extern void close_global_hooks(void);
extern void remove_thread_hooks( struct thread *thread );
+extern unsigned int get_active_hooks(void);
/* queue functions */