Store the hook table in the thread queue instead of the thread
structure, and make sure the queue is allocated when setting a hook.

diff --git a/server/hook.c b/server/hook.c
index 83b540b..65bd3ba 100644
--- a/server/hook.c
+++ b/server/hook.c
@@ -94,12 +94,12 @@
 static struct hook *add_hook( struct thread *thread, int index )
 {
     struct hook *hook;
-    struct hook_table *table = thread ? thread->hooks : global_hooks;
+    struct hook_table *table = thread ? get_queue_hooks(thread) : global_hooks;
 
     if (!table)
     {
         if (!(table = alloc_hook_table())) return NULL;
-        if (thread) thread->hooks = table;
+        if (thread) set_queue_hooks( thread, table );
         else global_hooks = table;
     }
     if (!(hook = mem_alloc( sizeof(*hook) ))) return NULL;
@@ -129,7 +129,7 @@
 static struct hook *find_hook( struct thread *thread, int index, void *proc )
 {
     struct list *p;
-    struct hook_table *table = thread->hooks;
+    struct hook_table *table = get_queue_hooks( thread );
 
     if (table)
     {
@@ -145,7 +145,7 @@
 /* get the hook table that a given hook belongs to */
 inline static struct hook_table *get_table( struct hook *hook )
 {
-    return hook->thread ? hook->thread->hooks : global_hooks;
+    return hook->thread ? get_queue_hooks(hook->thread) : global_hooks;
 }
 
 /* get the first hook in the chain */
@@ -304,7 +304,7 @@
 DECL_HANDLER(start_hook_chain)
 {
     struct hook *hook;
-    struct hook_table *table = current->hooks;
+    struct hook_table *table = get_queue_hooks( current );
 
     if (req->id < WH_MINHOOK || req->id > WH_MAXHOOK)
     {
@@ -330,7 +330,7 @@
 /* finished calling a hook chain */
 DECL_HANDLER(finish_hook_chain)
 {
-    struct hook_table *table = current->hooks;
+    struct hook_table *table = get_queue_hooks( current );
     int index = req->id - WH_MINHOOK;
 
     if (req->id < WH_MINHOOK || req->id > WH_MAXHOOK)
diff --git a/server/queue.c b/server/queue.c
index 5315886..70dfe63 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -124,6 +124,7 @@
     struct timer          *next_timer;    /* next timer to expire */
     struct timeout_user   *timeout;       /* timeout for next timer to expire */
     struct thread_input   *input;         /* thread input descriptor */
+    struct hook_table     *hooks;         /* hook table */
 };
 
 static void msg_queue_dump( struct object *obj, int verbose );
@@ -219,6 +220,7 @@
         queue->next_timer      = NULL;
         queue->timeout         = NULL;
         queue->input           = (struct thread_input *)grab_object( input );
+        queue->hooks           = NULL;
         for (i = 0; i < NB_MSG_KINDS; i++)
             queue->msg_list[i].first = queue->msg_list[i].last = NULL;
 
@@ -251,6 +253,22 @@
     thread->queue = NULL;
 }
 
+/* get the hook table for a given thread */
+struct hook_table *get_queue_hooks( struct thread *thread )
+{
+    if (!thread->queue) return NULL;
+    return thread->queue->hooks;
+}
+
+/* set the hook table for a given thread, allocating the queue if needed */
+void set_queue_hooks( struct thread *thread, struct hook_table *hooks )
+{
+    struct msg_queue *queue = thread->queue;
+    if (!queue) queue = create_msg_queue( thread, NULL );
+    if (queue->hooks) release_object( queue->hooks );
+    queue->hooks = hooks;
+}
+
 /* check the queue status */
 inline static int is_signaled( struct msg_queue *queue )
 {
@@ -645,6 +663,7 @@
     }
     if (queue->timeout) remove_timeout_user( queue->timeout );
     if (queue->input) release_object( queue->input );
+    if (queue->hooks) release_object( queue->hooks );
 }
 
 static void thread_input_dump( struct object *obj, int verbose )
diff --git a/server/thread.c b/server/thread.c
index a600bf1..799ede5 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -118,7 +118,6 @@
     thread->debug_ctx       = NULL;
     thread->debug_event     = NULL;
     thread->queue           = NULL;
-    thread->hooks           = NULL;
     thread->wait            = NULL;
     thread->system_apc.head = NULL;
     thread->system_apc.tail = NULL;
@@ -208,7 +207,6 @@
     if (thread->request_fd) release_object( thread->request_fd );
     if (thread->reply_fd) release_object( thread->reply_fd );
     if (thread->wait_fd) release_object( thread->wait_fd );
-    if (thread->hooks) release_object( thread->hooks );
     free_msg_queue( thread );
     cleanup_clipboard_thread(thread);
     destroy_thread_windows( thread );
@@ -225,7 +223,6 @@
     thread->request_fd = NULL;
     thread->reply_fd = NULL;
     thread->wait_fd = NULL;
-    thread->hooks = NULL;
 
     if (thread == booting_thread)  /* killing booting thread */
     {
diff --git a/server/thread.h b/server/thread.h
index b0fa9c3..2100518 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -32,7 +32,6 @@
 struct debug_ctx;
 struct debug_event;
 struct msg_queue;
-struct hook_table;
 
 enum run_state
 {
@@ -67,7 +66,6 @@
     struct debug_ctx      *debug_ctx;     /* debugger context if this thread is a debugger */
     struct debug_event    *debug_event;   /* debug event being sent to debugger */
     struct msg_queue      *queue;         /* message queue */
-    struct hook_table     *hooks;         /* hooks table */
     struct thread_wait    *wait;          /* current wait condition if sleeping */
     struct apc_queue       system_apc;    /* queue of system async procedure calls */
     struct apc_queue       user_apc;      /* queue of user async procedure calls */
diff --git a/server/user.h b/server/user.h
index 0d038b6..e4229a0 100644
--- a/server/user.h
+++ b/server/user.h
@@ -26,6 +26,7 @@
 struct thread;
 struct window;
 struct msg_queue;
+struct hook_table;
 
 enum user_object
 {
@@ -53,6 +54,8 @@
 /* queue functions */
 
 extern void free_msg_queue( struct thread *thread );
+extern struct hook_table *get_queue_hooks( struct thread *thread );
+extern void set_queue_hooks( struct thread *thread, struct hook_table *hooks );
 extern void inc_queue_paint_count( struct thread *thread, int incr );
 extern void queue_cleanup_window( struct thread *thread, user_handle_t win );
 extern int attach_thread_input( struct thread *thread_from, struct thread *thread_to );