server: Post WM_HOTKEY when a hotkey is pressed.
[wine] / server / queue.c
1 /*
2  * Server-side message queues
3  *
4  * Copyright (C) 2000 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35 #include "winternl.h"
36
37 #include "handle.h"
38 #include "file.h"
39 #include "thread.h"
40 #include "process.h"
41 #include "request.h"
42 #include "user.h"
43
44 #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
45 #define WM_NCMOUSELAST  (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST))
46
47 enum message_kind { SEND_MESSAGE, POST_MESSAGE };
48 #define NB_MSG_KINDS (POST_MESSAGE+1)
49
50
51 struct message_result
52 {
53     struct list            sender_entry;  /* entry in sender list */
54     struct message        *msg;           /* message the result is for */
55     struct message_result *recv_next;     /* next in receiver list */
56     struct msg_queue      *sender;        /* sender queue */
57     struct msg_queue      *receiver;      /* receiver queue */
58     int                    replied;       /* has it been replied to? */
59     unsigned int           error;         /* error code to pass back to sender */
60     lparam_t               result;        /* reply result */
61     struct message        *hardware_msg;  /* hardware message if low-level hook result */
62     struct desktop        *desktop;       /* desktop for hardware message */
63     struct message        *callback_msg;  /* message to queue for callback */
64     void                  *data;          /* message reply data */
65     unsigned int           data_size;     /* size of message reply data */
66     struct timeout_user   *timeout;       /* result timeout */
67 };
68
69 struct message
70 {
71     struct list            entry;     /* entry in message list */
72     enum message_type      type;      /* message type */
73     user_handle_t          win;       /* window handle */
74     unsigned int           msg;       /* message code */
75     lparam_t               wparam;    /* parameters */
76     lparam_t               lparam;    /* parameters */
77     unsigned int           time;      /* message time */
78     void                  *data;      /* message data for sent messages */
79     unsigned int           data_size; /* size of message data */
80     unsigned int           unique_id; /* unique id for nested hw message waits */
81     struct message_result *result;    /* result in sender queue */
82 };
83
84 struct timer
85 {
86     struct list     entry;     /* entry in timer list */
87     timeout_t       when;      /* next expiration */
88     unsigned int    rate;      /* timer rate in ms */
89     user_handle_t   win;       /* window handle */
90     unsigned int    msg;       /* message to post */
91     lparam_t        id;        /* timer id */
92     lparam_t        lparam;    /* lparam for message */
93 };
94
95 struct thread_input
96 {
97     struct object          obj;           /* object header */
98     struct desktop        *desktop;       /* desktop that this thread input belongs to */
99     user_handle_t          focus;         /* focus window */
100     user_handle_t          capture;       /* capture window */
101     user_handle_t          active;        /* active window */
102     user_handle_t          menu_owner;    /* current menu owner window */
103     user_handle_t          move_size;     /* current moving/resizing window */
104     user_handle_t          caret;         /* caret window */
105     rectangle_t            caret_rect;    /* caret rectangle */
106     int                    caret_hide;    /* caret hide count */
107     int                    caret_state;   /* caret on/off state */
108     user_handle_t          cursor;        /* current cursor */
109     int                    cursor_count;  /* cursor show count */
110     struct list            msg_list;      /* list of hardware messages */
111     unsigned char          keystate[256]; /* state of each key */
112 };
113
114 struct msg_queue
115 {
116     struct object          obj;             /* object header */
117     struct fd             *fd;              /* optional file descriptor to poll */
118     unsigned int           wake_bits;       /* wakeup bits */
119     unsigned int           wake_mask;       /* wakeup mask */
120     unsigned int           changed_bits;    /* changed wakeup bits */
121     unsigned int           changed_mask;    /* changed wakeup mask */
122     int                    paint_count;     /* pending paint messages count */
123     int                    quit_message;    /* is there a pending quit message? */
124     int                    exit_code;       /* exit code of pending quit message */
125     int                    cursor_count;    /* per-queue cursor show count */
126     struct list            msg_list[NB_MSG_KINDS];  /* lists of messages */
127     struct list            send_result;     /* stack of sent messages waiting for result */
128     struct list            callback_result; /* list of callback messages waiting for result */
129     struct message_result *recv_result;     /* stack of received messages waiting for result */
130     struct list            pending_timers;  /* list of pending timers */
131     struct list            expired_timers;  /* list of expired timers */
132     lparam_t               next_timer_id;   /* id for the next timer with a 0 window */
133     struct timeout_user   *timeout;         /* timeout for next timer to expire */
134     struct thread_input   *input;           /* thread input descriptor */
135     struct hook_table     *hooks;           /* hook table */
136     timeout_t              last_get_msg;    /* time of last get message call */
137 };
138
139 struct hotkey
140 {
141     struct list         entry;        /* entry in desktop hotkey list */
142     struct msg_queue   *queue;        /* queue owning this hotkey */
143     user_handle_t       win;          /* window handle */
144     int                 id;           /* hotkey id */
145     unsigned int        vkey;         /* virtual key code */
146     unsigned int        flags;        /* key modifiers */
147 };
148
149 static void msg_queue_dump( struct object *obj, int verbose );
150 static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry );
151 static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry );
152 static int msg_queue_signaled( struct object *obj, struct thread *thread );
153 static int msg_queue_satisfied( struct object *obj, struct thread *thread );
154 static void msg_queue_destroy( struct object *obj );
155 static void msg_queue_poll_event( struct fd *fd, int event );
156 static void thread_input_dump( struct object *obj, int verbose );
157 static void thread_input_destroy( struct object *obj );
158 static void timer_callback( void *private );
159
160 static const struct object_ops msg_queue_ops =
161 {
162     sizeof(struct msg_queue),  /* size */
163     msg_queue_dump,            /* dump */
164     no_get_type,               /* get_type */
165     msg_queue_add_queue,       /* add_queue */
166     msg_queue_remove_queue,    /* remove_queue */
167     msg_queue_signaled,        /* signaled */
168     msg_queue_satisfied,       /* satisfied */
169     no_signal,                 /* signal */
170     no_get_fd,                 /* get_fd */
171     no_map_access,             /* map_access */
172     default_get_sd,            /* get_sd */
173     default_set_sd,            /* set_sd */
174     no_lookup_name,            /* lookup_name */
175     no_open_file,              /* open_file */
176     no_close_handle,           /* close_handle */
177     msg_queue_destroy          /* destroy */
178 };
179
180 static const struct fd_ops msg_queue_fd_ops =
181 {
182     NULL,                        /* get_poll_events */
183     msg_queue_poll_event,        /* poll_event */
184     NULL,                        /* flush */
185     NULL,                        /* get_fd_type */
186     NULL,                        /* ioctl */
187     NULL,                        /* queue_async */
188     NULL,                        /* reselect_async */
189     NULL                         /* cancel async */
190 };
191
192
193 static const struct object_ops thread_input_ops =
194 {
195     sizeof(struct thread_input),  /* size */
196     thread_input_dump,            /* dump */
197     no_get_type,                  /* get_type */
198     no_add_queue,                 /* add_queue */
199     NULL,                         /* remove_queue */
200     NULL,                         /* signaled */
201     NULL,                         /* satisfied */
202     no_signal,                    /* signal */
203     no_get_fd,                    /* get_fd */
204     no_map_access,                /* map_access */
205     default_get_sd,               /* get_sd */
206     default_set_sd,               /* set_sd */
207     no_lookup_name,               /* lookup_name */
208     no_open_file,                 /* open_file */
209     no_close_handle,              /* close_handle */
210     thread_input_destroy          /* destroy */
211 };
212
213 /* pointer to input structure of foreground thread */
214 static unsigned int last_input_time;
215
216 static void queue_hardware_message( struct desktop *desktop, struct message *msg, int always_queue );
217 static void free_message( struct message *msg );
218
219 /* set the caret window in a given thread input */
220 static void set_caret_window( struct thread_input *input, user_handle_t win )
221 {
222     if (!win || win != input->caret)
223     {
224         input->caret_rect.left   = 0;
225         input->caret_rect.top    = 0;
226         input->caret_rect.right  = 0;
227         input->caret_rect.bottom = 0;
228     }
229     input->caret             = win;
230     input->caret_hide        = 1;
231     input->caret_state       = 0;
232 }
233
234 /* create a thread input object */
235 static struct thread_input *create_thread_input( struct thread *thread )
236 {
237     struct thread_input *input;
238
239     if ((input = alloc_object( &thread_input_ops )))
240     {
241         input->focus        = 0;
242         input->capture      = 0;
243         input->active       = 0;
244         input->menu_owner   = 0;
245         input->move_size    = 0;
246         input->cursor       = 0;
247         input->cursor_count = 0;
248         list_init( &input->msg_list );
249         set_caret_window( input, 0 );
250         memset( input->keystate, 0, sizeof(input->keystate) );
251
252         if (!(input->desktop = get_thread_desktop( thread, 0 /* FIXME: access rights */ )))
253         {
254             release_object( input );
255             return NULL;
256         }
257     }
258     return input;
259 }
260
261 /* create a message queue object */
262 static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_input *input )
263 {
264     struct thread_input *new_input = NULL;
265     struct msg_queue *queue;
266     int i;
267
268     if (!input)
269     {
270         if (!(new_input = create_thread_input( thread ))) return NULL;
271         input = new_input;
272     }
273
274     if ((queue = alloc_object( &msg_queue_ops )))
275     {
276         queue->fd              = NULL;
277         queue->wake_bits       = 0;
278         queue->wake_mask       = 0;
279         queue->changed_bits    = 0;
280         queue->changed_mask    = 0;
281         queue->paint_count     = 0;
282         queue->quit_message    = 0;
283         queue->cursor_count    = 0;
284         queue->recv_result     = NULL;
285         queue->next_timer_id   = 0x7fff;
286         queue->timeout         = NULL;
287         queue->input           = (struct thread_input *)grab_object( input );
288         queue->hooks           = NULL;
289         queue->last_get_msg    = current_time;
290         list_init( &queue->send_result );
291         list_init( &queue->callback_result );
292         list_init( &queue->pending_timers );
293         list_init( &queue->expired_timers );
294         for (i = 0; i < NB_MSG_KINDS; i++) list_init( &queue->msg_list[i] );
295
296         thread->queue = queue;
297     }
298     if (new_input) release_object( new_input );
299     return queue;
300 }
301
302 /* free the message queue of a thread at thread exit */
303 void free_msg_queue( struct thread *thread )
304 {
305     remove_thread_hooks( thread );
306     if (!thread->queue) return;
307     release_object( thread->queue );
308     thread->queue = NULL;
309 }
310
311 /* change the thread input data of a given thread */
312 static int assign_thread_input( struct thread *thread, struct thread_input *new_input )
313 {
314     struct msg_queue *queue = thread->queue;
315
316     if (!queue)
317     {
318         thread->queue = create_msg_queue( thread, new_input );
319         return thread->queue != NULL;
320     }
321     if (queue->input)
322     {
323         queue->input->cursor_count -= queue->cursor_count;
324         release_object( queue->input );
325     }
326     queue->input = (struct thread_input *)grab_object( new_input );
327     new_input->cursor_count += queue->cursor_count;
328     return 1;
329 }
330
331 /* set the cursor position and queue the corresponding mouse message */
332 static void set_cursor_pos( struct desktop *desktop, int x, int y )
333 {
334     struct hardware_msg_data *msg_data;
335     struct message *msg;
336
337     if (!(msg = mem_alloc( sizeof(*msg) ))) return;
338     if (!(msg_data = mem_alloc( sizeof(*msg_data) )))
339     {
340         free( msg );
341         return;
342     }
343     memset( msg_data, 0, sizeof(*msg_data) );
344
345     msg->type      = MSG_HARDWARE;
346     msg->win       = 0;
347     msg->msg       = WM_MOUSEMOVE;
348     msg->wparam    = 0;
349     msg->lparam    = 0;
350     msg->time      = get_tick_count();
351     msg->result    = NULL;
352     msg->data      = msg_data;
353     msg->data_size = sizeof(*msg_data);
354     msg_data->x    = x;
355     msg_data->y    = y;
356     queue_hardware_message( desktop, msg, 1 );
357 }
358
359 /* set the cursor clip rectangle */
360 static void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect )
361 {
362     rectangle_t top_rect, new_rect;
363     int x, y;
364
365     get_top_window_rectangle( desktop, &top_rect );
366     if (!rect || !intersect_rect( &new_rect, &top_rect, rect )) new_rect = top_rect;
367     desktop->cursor.clip = new_rect;
368     if (desktop->cursor.clip_msg)
369         post_desktop_message( desktop, desktop->cursor.clip_msg, rect != NULL, 0 );
370
371     /* warp the mouse to be inside the clip rect */
372     x = min( max( desktop->cursor.x, desktop->cursor.clip.left ), desktop->cursor.clip.right-1 );
373     y = min( max( desktop->cursor.y, desktop->cursor.clip.top ), desktop->cursor.clip.bottom-1 );
374     if (x != desktop->cursor.x || y != desktop->cursor.y) set_cursor_pos( desktop, x, y );
375 }
376
377 /* change the foreground input and reset the cursor clip rect */
378 static void set_foreground_input( struct desktop *desktop, struct thread_input *input )
379 {
380     if (desktop->foreground_input == input) return;
381     set_clip_rectangle( desktop, NULL );
382     desktop->foreground_input = input;
383 }
384
385 /* get the hook table for a given thread */
386 struct hook_table *get_queue_hooks( struct thread *thread )
387 {
388     if (!thread->queue) return NULL;
389     return thread->queue->hooks;
390 }
391
392 /* set the hook table for a given thread, allocating the queue if needed */
393 void set_queue_hooks( struct thread *thread, struct hook_table *hooks )
394 {
395     struct msg_queue *queue = thread->queue;
396     if (!queue && !(queue = create_msg_queue( thread, NULL ))) return;
397     if (queue->hooks) release_object( queue->hooks );
398     queue->hooks = hooks;
399 }
400
401 /* check the queue status */
402 static inline int is_signaled( struct msg_queue *queue )
403 {
404     return ((queue->wake_bits & queue->wake_mask) || (queue->changed_bits & queue->changed_mask));
405 }
406
407 /* set some queue bits */
408 static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits )
409 {
410     queue->wake_bits |= bits;
411     queue->changed_bits |= bits;
412     if (is_signaled( queue )) wake_up( &queue->obj, 0 );
413 }
414
415 /* clear some queue bits */
416 static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits )
417 {
418     queue->wake_bits &= ~bits;
419     queue->changed_bits &= ~bits;
420 }
421
422 /* check whether msg is a keyboard message */
423 static inline int is_keyboard_msg( struct message *msg )
424 {
425     return (msg->msg >= WM_KEYFIRST && msg->msg <= WM_KEYLAST);
426 }
427
428 /* check if message is matched by the filter */
429 static inline int check_msg_filter( unsigned int msg, unsigned int first, unsigned int last )
430 {
431     return (msg >= first && msg <= last);
432 }
433
434 /* check whether a message filter contains at least one potential hardware message */
435 static inline int filter_contains_hw_range( unsigned int first, unsigned int last )
436 {
437     /* hardware message ranges are (in numerical order):
438      *   WM_NCMOUSEFIRST .. WM_NCMOUSELAST
439      *   WM_KEYFIRST .. WM_KEYLAST
440      *   WM_MOUSEFIRST .. WM_MOUSELAST
441      */
442     if (last < WM_NCMOUSEFIRST) return 0;
443     if (first > WM_NCMOUSELAST && last < WM_KEYFIRST) return 0;
444     if (first > WM_KEYLAST && last < WM_MOUSEFIRST) return 0;
445     if (first > WM_MOUSELAST) return 0;
446     return 1;
447 }
448
449 /* get the QS_* bit corresponding to a given hardware message */
450 static inline int get_hardware_msg_bit( struct message *msg )
451 {
452     if (msg->msg == WM_MOUSEMOVE || msg->msg == WM_NCMOUSEMOVE) return QS_MOUSEMOVE;
453     if (is_keyboard_msg( msg )) return QS_KEY;
454     return QS_MOUSEBUTTON;
455 }
456
457 /* get the current thread queue, creating it if needed */
458 static inline struct msg_queue *get_current_queue(void)
459 {
460     struct msg_queue *queue = current->queue;
461     if (!queue) queue = create_msg_queue( current, NULL );
462     return queue;
463 }
464
465 /* get a (pseudo-)unique id to tag hardware messages */
466 static inline unsigned int get_unique_id(void)
467 {
468     static unsigned int id;
469     if (!++id) id = 1;  /* avoid an id of 0 */
470     return id;
471 }
472
473 /* try to merge a message with the last in the list; return 1 if successful */
474 static int merge_message( struct thread_input *input, const struct message *msg )
475 {
476     struct message *prev;
477     struct list *ptr;
478
479     if (msg->msg != WM_MOUSEMOVE) return 0;
480     if (!(ptr = list_tail( &input->msg_list ))) return 0;
481     prev = LIST_ENTRY( ptr, struct message, entry );
482     if (prev->result) return 0;
483     if (prev->win && msg->win && prev->win != msg->win) return 0;
484     if (prev->msg != msg->msg) return 0;
485     if (prev->type != msg->type) return 0;
486     /* now we can merge it */
487     prev->wparam  = msg->wparam;
488     prev->lparam  = msg->lparam;
489     prev->time    = msg->time;
490     if (msg->type == MSG_HARDWARE && prev->data && msg->data)
491     {
492         struct hardware_msg_data *prev_data = prev->data;
493         struct hardware_msg_data *msg_data = msg->data;
494         prev_data->x     = msg_data->x;
495         prev_data->y     = msg_data->y;
496         prev_data->info  = msg_data->info;
497     }
498     return 1;
499 }
500
501 /* free a result structure */
502 static void free_result( struct message_result *result )
503 {
504     if (result->timeout) remove_timeout_user( result->timeout );
505     free( result->data );
506     if (result->callback_msg) free_message( result->callback_msg );
507     if (result->hardware_msg) free_message( result->hardware_msg );
508     if (result->desktop) release_object( result->desktop );
509     free( result );
510 }
511
512 /* remove the result from the sender list it is on */
513 static inline void remove_result_from_sender( struct message_result *result )
514 {
515     assert( result->sender );
516
517     list_remove( &result->sender_entry );
518     result->sender = NULL;
519     if (!result->receiver) free_result( result );
520 }
521
522 /* store the message result in the appropriate structure */
523 static void store_message_result( struct message_result *res, lparam_t result, unsigned int error )
524 {
525     res->result  = result;
526     res->error   = error;
527     res->replied = 1;
528     if (res->timeout)
529     {
530         remove_timeout_user( res->timeout );
531         res->timeout = NULL;
532     }
533
534     if (res->hardware_msg)
535     {
536         if (!error && result)  /* rejected by the hook */
537             free_message( res->hardware_msg );
538         else
539             queue_hardware_message( res->desktop, res->hardware_msg, 0 );
540
541         res->hardware_msg = NULL;
542     }
543
544     if (res->sender)
545     {
546         if (res->callback_msg)
547         {
548             /* queue the callback message in the sender queue */
549             struct callback_msg_data *data = res->callback_msg->data;
550             data->result = result;
551             list_add_tail( &res->sender->msg_list[SEND_MESSAGE], &res->callback_msg->entry );
552             set_queue_bits( res->sender, QS_SENDMESSAGE );
553             res->callback_msg = NULL;
554             remove_result_from_sender( res );
555         }
556         else
557         {
558             /* wake sender queue if waiting on this result */
559             if (list_head(&res->sender->send_result) == &res->sender_entry)
560                 set_queue_bits( res->sender, QS_SMRESULT );
561         }
562     }
563     else if (!res->receiver) free_result( res );
564 }
565
566 /* free a message when deleting a queue or window */
567 static void free_message( struct message *msg )
568 {
569     struct message_result *result = msg->result;
570     if (result)
571     {
572         result->msg = NULL;
573         result->receiver = NULL;
574         store_message_result( result, 0, STATUS_ACCESS_DENIED /*FIXME*/ );
575     }
576     free( msg->data );
577     free( msg );
578 }
579
580 /* remove (and free) a message from a message list */
581 static void remove_queue_message( struct msg_queue *queue, struct message *msg,
582                                   enum message_kind kind )
583 {
584     list_remove( &msg->entry );
585     switch(kind)
586     {
587     case SEND_MESSAGE:
588         if (list_empty( &queue->msg_list[kind] )) clear_queue_bits( queue, QS_SENDMESSAGE );
589         break;
590     case POST_MESSAGE:
591         if (list_empty( &queue->msg_list[kind] ) && !queue->quit_message)
592             clear_queue_bits( queue, QS_POSTMESSAGE|QS_ALLPOSTMESSAGE );
593         break;
594     }
595     free_message( msg );
596 }
597
598 /* message timed out without getting a reply */
599 static void result_timeout( void *private )
600 {
601     struct message_result *result = private;
602
603     assert( !result->replied );
604
605     result->timeout = NULL;
606
607     if (result->msg)  /* not received yet */
608     {
609         struct message *msg = result->msg;
610
611         result->msg = NULL;
612         msg->result = NULL;
613         remove_queue_message( result->receiver, msg, SEND_MESSAGE );
614         result->receiver = NULL;
615     }
616     store_message_result( result, 0, STATUS_TIMEOUT );
617 }
618
619 /* allocate and fill a message result structure */
620 static struct message_result *alloc_message_result( struct msg_queue *send_queue,
621                                                     struct msg_queue *recv_queue,
622                                                     struct message *msg, timeout_t timeout )
623 {
624     struct message_result *result = mem_alloc( sizeof(*result) );
625     if (result)
626     {
627         result->msg          = msg;
628         result->sender       = send_queue;
629         result->receiver     = recv_queue;
630         result->replied      = 0;
631         result->data         = NULL;
632         result->data_size    = 0;
633         result->timeout      = NULL;
634         result->hardware_msg = NULL;
635         result->desktop      = NULL;
636         result->callback_msg = NULL;
637
638         if (msg->type == MSG_CALLBACK)
639         {
640             struct message *callback_msg = mem_alloc( sizeof(*callback_msg) );
641
642             if (!callback_msg)
643             {
644                 free( result );
645                 return NULL;
646             }
647             callback_msg->type      = MSG_CALLBACK_RESULT;
648             callback_msg->win       = msg->win;
649             callback_msg->msg       = msg->msg;
650             callback_msg->wparam    = 0;
651             callback_msg->lparam    = 0;
652             callback_msg->time      = get_tick_count();
653             callback_msg->result    = NULL;
654             /* steal the data from the original message */
655             callback_msg->data      = msg->data;
656             callback_msg->data_size = msg->data_size;
657             msg->data = NULL;
658             msg->data_size = 0;
659
660             result->callback_msg = callback_msg;
661             list_add_head( &send_queue->callback_result, &result->sender_entry );
662         }
663         else if (send_queue) list_add_head( &send_queue->send_result, &result->sender_entry );
664
665         if (timeout != TIMEOUT_INFINITE)
666             result->timeout = add_timeout_user( timeout, result_timeout, result );
667     }
668     return result;
669 }
670
671 /* receive a message, removing it from the sent queue */
672 static void receive_message( struct msg_queue *queue, struct message *msg,
673                              struct get_message_reply *reply )
674 {
675     struct message_result *result = msg->result;
676
677     reply->total = msg->data_size;
678     if (msg->data_size > get_reply_max_size())
679     {
680         set_error( STATUS_BUFFER_OVERFLOW );
681         return;
682     }
683     reply->type   = msg->type;
684     reply->win    = msg->win;
685     reply->msg    = msg->msg;
686     reply->wparam = msg->wparam;
687     reply->lparam = msg->lparam;
688     reply->time   = msg->time;
689
690     if (msg->data) set_reply_data_ptr( msg->data, msg->data_size );
691
692     list_remove( &msg->entry );
693     /* put the result on the receiver result stack */
694     if (result)
695     {
696         result->msg = NULL;
697         result->recv_next  = queue->recv_result;
698         queue->recv_result = result;
699     }
700     free( msg );
701     if (list_empty( &queue->msg_list[SEND_MESSAGE] )) clear_queue_bits( queue, QS_SENDMESSAGE );
702 }
703
704 /* set the result of the current received message */
705 static void reply_message( struct msg_queue *queue, lparam_t result,
706                            unsigned int error, int remove, const void *data, data_size_t len )
707 {
708     struct message_result *res = queue->recv_result;
709
710     if (remove)
711     {
712         queue->recv_result = res->recv_next;
713         res->receiver = NULL;
714         if (!res->sender && !res->hardware_msg)  /* no one waiting for it */
715         {
716             free_result( res );
717             return;
718         }
719     }
720     if (!res->replied)
721     {
722         if (len && (res->data = memdup( data, len ))) res->data_size = len;
723         store_message_result( res, result, error );
724     }
725 }
726
727 static int match_window( user_handle_t win, user_handle_t msg_win )
728 {
729     if (!win) return 1;
730     if (win == -1 || win == 1) return !msg_win;
731     if (msg_win == win) return 1;
732     return is_child_window( win, msg_win );
733 }
734
735 /* retrieve a posted message */
736 static int get_posted_message( struct msg_queue *queue, user_handle_t win,
737                                unsigned int first, unsigned int last, unsigned int flags,
738                                struct get_message_reply *reply )
739 {
740     struct message *msg;
741
742     /* check against the filters */
743     LIST_FOR_EACH_ENTRY( msg, &queue->msg_list[POST_MESSAGE], struct message, entry )
744     {
745         if (!match_window( win, msg->win )) continue;
746         if (!check_msg_filter( msg->msg, first, last )) continue;
747         goto found; /* found one */
748     }
749     return 0;
750
751     /* return it to the app */
752 found:
753     reply->total = msg->data_size;
754     if (msg->data_size > get_reply_max_size())
755     {
756         set_error( STATUS_BUFFER_OVERFLOW );
757         return 1;
758     }
759     reply->type   = msg->type;
760     reply->win    = msg->win;
761     reply->msg    = msg->msg;
762     reply->wparam = msg->wparam;
763     reply->lparam = msg->lparam;
764     reply->time   = msg->time;
765
766     if (flags & PM_REMOVE)
767     {
768         if (msg->data)
769         {
770             set_reply_data_ptr( msg->data, msg->data_size );
771             msg->data = NULL;
772             msg->data_size = 0;
773         }
774         remove_queue_message( queue, msg, POST_MESSAGE );
775     }
776     else if (msg->data) set_reply_data( msg->data, msg->data_size );
777
778     return 1;
779 }
780
781 static int get_quit_message( struct msg_queue *queue, unsigned int flags,
782                              struct get_message_reply *reply )
783 {
784     if (queue->quit_message)
785     {
786         reply->total  = 0;
787         reply->type   = MSG_POSTED;
788         reply->win    = 0;
789         reply->msg    = WM_QUIT;
790         reply->wparam = queue->exit_code;
791         reply->lparam = 0;
792         reply->time   = get_tick_count();
793
794         if (flags & PM_REMOVE)
795         {
796             queue->quit_message = 0;
797             if (list_empty( &queue->msg_list[POST_MESSAGE] ))
798                 clear_queue_bits( queue, QS_POSTMESSAGE|QS_ALLPOSTMESSAGE );
799         }
800         return 1;
801     }
802     else
803         return 0;
804 }
805
806 /* empty a message list and free all the messages */
807 static void empty_msg_list( struct list *list )
808 {
809     struct list *ptr;
810
811     while ((ptr = list_head( list )) != NULL)
812     {
813         struct message *msg = LIST_ENTRY( ptr, struct message, entry );
814         list_remove( &msg->entry );
815         free_message( msg );
816     }
817 }
818
819 /* cleanup all pending results when deleting a queue */
820 static void cleanup_results( struct msg_queue *queue )
821 {
822     struct list *entry;
823
824     while ((entry = list_head( &queue->send_result )) != NULL)
825     {
826         remove_result_from_sender( LIST_ENTRY( entry, struct message_result, sender_entry ) );
827     }
828
829     while ((entry = list_head( &queue->callback_result )) != NULL)
830     {
831         remove_result_from_sender( LIST_ENTRY( entry, struct message_result, sender_entry ) );
832     }
833
834     while (queue->recv_result)
835         reply_message( queue, 0, STATUS_ACCESS_DENIED /*FIXME*/, 1, NULL, 0 );
836 }
837
838 /* check if the thread owning the queue is hung (not checking for messages) */
839 static int is_queue_hung( struct msg_queue *queue )
840 {
841     struct wait_queue_entry *entry;
842
843     if (current_time - queue->last_get_msg <= 5 * TICKS_PER_SEC)
844         return 0;  /* less than 5 seconds since last get message -> not hung */
845
846     LIST_FOR_EACH_ENTRY( entry, &queue->obj.wait_queue, struct wait_queue_entry, entry )
847     {
848         if (entry->thread->queue == queue)
849             return 0;  /* thread is waiting on queue -> not hung */
850     }
851     return 1;
852 }
853
854 static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry )
855 {
856     struct msg_queue *queue = (struct msg_queue *)obj;
857     struct process *process = entry->thread->process;
858
859     /* a thread can only wait on its own queue */
860     if (entry->thread->queue != queue)
861     {
862         set_error( STATUS_ACCESS_DENIED );
863         return 0;
864     }
865     if (process->idle_event && !(queue->wake_mask & QS_SMRESULT)) set_event( process->idle_event );
866
867     if (queue->fd && list_empty( &obj->wait_queue ))  /* first on the queue */
868         set_fd_events( queue->fd, POLLIN );
869     add_queue( obj, entry );
870     return 1;
871 }
872
873 static void msg_queue_remove_queue(struct object *obj, struct wait_queue_entry *entry )
874 {
875     struct msg_queue *queue = (struct msg_queue *)obj;
876
877     remove_queue( obj, entry );
878     if (queue->fd && list_empty( &obj->wait_queue ))  /* last on the queue is gone */
879         set_fd_events( queue->fd, 0 );
880 }
881
882 static void msg_queue_dump( struct object *obj, int verbose )
883 {
884     struct msg_queue *queue = (struct msg_queue *)obj;
885     fprintf( stderr, "Msg queue bits=%x mask=%x\n",
886              queue->wake_bits, queue->wake_mask );
887 }
888
889 static int msg_queue_signaled( struct object *obj, struct thread *thread )
890 {
891     struct msg_queue *queue = (struct msg_queue *)obj;
892     int ret = 0;
893
894     if (queue->fd)
895     {
896         if ((ret = check_fd_events( queue->fd, POLLIN )))
897             /* stop waiting on select() if we are signaled */
898             set_fd_events( queue->fd, 0 );
899         else if (!list_empty( &obj->wait_queue ))
900             /* restart waiting on poll() if we are no longer signaled */
901             set_fd_events( queue->fd, POLLIN );
902     }
903     return ret || is_signaled( queue );
904 }
905
906 static int msg_queue_satisfied( struct object *obj, struct thread *thread )
907 {
908     struct msg_queue *queue = (struct msg_queue *)obj;
909     queue->wake_mask = 0;
910     queue->changed_mask = 0;
911     return 0;  /* Not abandoned */
912 }
913
914 static void msg_queue_destroy( struct object *obj )
915 {
916     struct msg_queue *queue = (struct msg_queue *)obj;
917     struct list *ptr;
918     struct hotkey *hotkey, *hotkey2;
919     int i;
920
921     cleanup_results( queue );
922     for (i = 0; i < NB_MSG_KINDS; i++) empty_msg_list( &queue->msg_list[i] );
923
924     LIST_FOR_EACH_ENTRY_SAFE( hotkey, hotkey2, &queue->input->desktop->hotkeys, struct hotkey, entry )
925     {
926         if (hotkey->queue == queue)
927         {
928             list_remove( &hotkey->entry );
929             free( hotkey );
930         }
931     }
932
933     while ((ptr = list_head( &queue->pending_timers )))
934     {
935         struct timer *timer = LIST_ENTRY( ptr, struct timer, entry );
936         list_remove( &timer->entry );
937         free( timer );
938     }
939     while ((ptr = list_head( &queue->expired_timers )))
940     {
941         struct timer *timer = LIST_ENTRY( ptr, struct timer, entry );
942         list_remove( &timer->entry );
943         free( timer );
944     }
945     if (queue->timeout) remove_timeout_user( queue->timeout );
946     if (queue->input)
947     {
948         queue->input->cursor_count -= queue->cursor_count;
949         release_object( queue->input );
950     }
951     if (queue->hooks) release_object( queue->hooks );
952     if (queue->fd) release_object( queue->fd );
953 }
954
955 static void msg_queue_poll_event( struct fd *fd, int event )
956 {
957     struct msg_queue *queue = get_fd_user( fd );
958     assert( queue->obj.ops == &msg_queue_ops );
959
960     if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 );
961     else set_fd_events( queue->fd, 0 );
962     wake_up( &queue->obj, 0 );
963 }
964
965 static void thread_input_dump( struct object *obj, int verbose )
966 {
967     struct thread_input *input = (struct thread_input *)obj;
968     fprintf( stderr, "Thread input focus=%08x capture=%08x active=%08x\n",
969              input->focus, input->capture, input->active );
970 }
971
972 static void thread_input_destroy( struct object *obj )
973 {
974     struct thread_input *input = (struct thread_input *)obj;
975
976     empty_msg_list( &input->msg_list );
977     if (input->desktop)
978     {
979         if (input->desktop->foreground_input == input) set_foreground_input( input->desktop, NULL );
980         release_object( input->desktop );
981     }
982 }
983
984 /* fix the thread input data when a window is destroyed */
985 static inline void thread_input_cleanup_window( struct msg_queue *queue, user_handle_t window )
986 {
987     struct thread_input *input = queue->input;
988
989     if (window == input->focus) input->focus = 0;
990     if (window == input->capture) input->capture = 0;
991     if (window == input->active) input->active = 0;
992     if (window == input->menu_owner) input->menu_owner = 0;
993     if (window == input->move_size) input->move_size = 0;
994     if (window == input->caret) set_caret_window( input, 0 );
995 }
996
997 /* check if the specified window can be set in the input data of a given queue */
998 static int check_queue_input_window( struct msg_queue *queue, user_handle_t window )
999 {
1000     struct thread *thread;
1001     int ret = 0;
1002
1003     if (!window) return 1;  /* we can always clear the data */
1004
1005     if ((thread = get_window_thread( window )))
1006     {
1007         ret = (queue->input == thread->queue->input);
1008         if (!ret) set_error( STATUS_ACCESS_DENIED );
1009         release_object( thread );
1010     }
1011     else set_error( STATUS_INVALID_HANDLE );
1012
1013     return ret;
1014 }
1015
1016 /* make sure the specified thread has a queue */
1017 int init_thread_queue( struct thread *thread )
1018 {
1019     if (thread->queue) return 1;
1020     return (create_msg_queue( thread, NULL ) != NULL);
1021 }
1022
1023 /* attach two thread input data structures */
1024 int attach_thread_input( struct thread *thread_from, struct thread *thread_to )
1025 {
1026     struct desktop *desktop;
1027     struct thread_input *input;
1028     int ret;
1029
1030     if (!thread_to->queue && !(thread_to->queue = create_msg_queue( thread_to, NULL ))) return 0;
1031     if (!(desktop = get_thread_desktop( thread_from, 0 ))) return 0;
1032     input = (struct thread_input *)grab_object( thread_to->queue->input );
1033     if (input->desktop != desktop)
1034     {
1035         set_error( STATUS_ACCESS_DENIED );
1036         release_object( input );
1037         release_object( desktop );
1038         return 0;
1039     }
1040     release_object( desktop );
1041
1042     ret = assign_thread_input( thread_from, input );
1043     if (ret) memset( input->keystate, 0, sizeof(input->keystate) );
1044     release_object( input );
1045     return ret;
1046 }
1047
1048 /* detach two thread input data structures */
1049 void detach_thread_input( struct thread *thread_from )
1050 {
1051     struct thread_input *input;
1052
1053     if ((input = create_thread_input( thread_from )))
1054     {
1055         assign_thread_input( thread_from, input );
1056         release_object( input );
1057     }
1058 }
1059
1060
1061 /* set the next timer to expire */
1062 static void set_next_timer( struct msg_queue *queue )
1063 {
1064     struct list *ptr;
1065
1066     if (queue->timeout)
1067     {
1068         remove_timeout_user( queue->timeout );
1069         queue->timeout = NULL;
1070     }
1071     if ((ptr = list_head( &queue->pending_timers )))
1072     {
1073         struct timer *timer = LIST_ENTRY( ptr, struct timer, entry );
1074         queue->timeout = add_timeout_user( timer->when, timer_callback, queue );
1075     }
1076     /* set/clear QS_TIMER bit */
1077     if (list_empty( &queue->expired_timers ))
1078         clear_queue_bits( queue, QS_TIMER );
1079     else
1080         set_queue_bits( queue, QS_TIMER );
1081 }
1082
1083 /* find a timer from its window and id */
1084 static struct timer *find_timer( struct msg_queue *queue, user_handle_t win,
1085                                  unsigned int msg, lparam_t id )
1086 {
1087     struct list *ptr;
1088
1089     /* we need to search both lists */
1090
1091     LIST_FOR_EACH( ptr, &queue->pending_timers )
1092     {
1093         struct timer *timer = LIST_ENTRY( ptr, struct timer, entry );
1094         if (timer->win == win && timer->msg == msg && timer->id == id) return timer;
1095     }
1096     LIST_FOR_EACH( ptr, &queue->expired_timers )
1097     {
1098         struct timer *timer = LIST_ENTRY( ptr, struct timer, entry );
1099         if (timer->win == win && timer->msg == msg && timer->id == id) return timer;
1100     }
1101     return NULL;
1102 }
1103
1104 /* callback for the next timer expiration */
1105 static void timer_callback( void *private )
1106 {
1107     struct msg_queue *queue = private;
1108     struct list *ptr;
1109
1110     queue->timeout = NULL;
1111     /* move on to the next timer */
1112     ptr = list_head( &queue->pending_timers );
1113     list_remove( ptr );
1114     list_add_tail( &queue->expired_timers, ptr );
1115     set_next_timer( queue );
1116 }
1117
1118 /* link a timer at its rightful place in the queue list */
1119 static void link_timer( struct msg_queue *queue, struct timer *timer )
1120 {
1121     struct list *ptr;
1122
1123     for (ptr = queue->pending_timers.next; ptr != &queue->pending_timers; ptr = ptr->next)
1124     {
1125         struct timer *t = LIST_ENTRY( ptr, struct timer, entry );
1126         if (t->when >= timer->when) break;
1127     }
1128     list_add_before( ptr, &timer->entry );
1129 }
1130
1131 /* remove a timer from the queue timer list and free it */
1132 static void free_timer( struct msg_queue *queue, struct timer *timer )
1133 {
1134     list_remove( &timer->entry );
1135     free( timer );
1136     set_next_timer( queue );
1137 }
1138
1139 /* restart an expired timer */
1140 static void restart_timer( struct msg_queue *queue, struct timer *timer )
1141 {
1142     list_remove( &timer->entry );
1143     while (timer->when <= current_time) timer->when += (timeout_t)timer->rate * 10000;
1144     link_timer( queue, timer );
1145     set_next_timer( queue );
1146 }
1147
1148 /* find an expired timer matching the filtering parameters */
1149 static struct timer *find_expired_timer( struct msg_queue *queue, user_handle_t win,
1150                                          unsigned int get_first, unsigned int get_last,
1151                                          int remove )
1152 {
1153     struct list *ptr;
1154
1155     LIST_FOR_EACH( ptr, &queue->expired_timers )
1156     {
1157         struct timer *timer = LIST_ENTRY( ptr, struct timer, entry );
1158         if (win && timer->win != win) continue;
1159         if (check_msg_filter( timer->msg, get_first, get_last ))
1160         {
1161             if (remove) restart_timer( queue, timer );
1162             return timer;
1163         }
1164     }
1165     return NULL;
1166 }
1167
1168 /* add a timer */
1169 static struct timer *set_timer( struct msg_queue *queue, unsigned int rate )
1170 {
1171     struct timer *timer = mem_alloc( sizeof(*timer) );
1172     if (timer)
1173     {
1174         timer->rate = max( rate, 1 );
1175         timer->when = current_time + (timeout_t)timer->rate * 10000;
1176         link_timer( queue, timer );
1177         /* check if we replaced the next timer */
1178         if (list_head( &queue->pending_timers ) == &timer->entry) set_next_timer( queue );
1179     }
1180     return timer;
1181 }
1182
1183 /* change the input key state for a given key */
1184 static void set_input_key_state( unsigned char *keystate, unsigned char key, int down )
1185 {
1186     if (down)
1187     {
1188         if (!(keystate[key] & 0x80)) keystate[key] ^= 0x01;
1189         keystate[key] |= down;
1190     }
1191     else keystate[key] &= ~0x80;
1192 }
1193
1194 /* update the input key state for a keyboard message */
1195 static void update_input_key_state( struct desktop *desktop, unsigned char *keystate,
1196                                     const struct message *msg )
1197 {
1198     unsigned char key;
1199     int down = 0;
1200
1201     switch (msg->msg)
1202     {
1203     case WM_LBUTTONDOWN:
1204         down = (keystate == desktop->keystate) ? 0xc0 : 0x80;
1205         /* fall through */
1206     case WM_LBUTTONUP:
1207         set_input_key_state( keystate, VK_LBUTTON, down );
1208         break;
1209     case WM_MBUTTONDOWN:
1210         down = (keystate == desktop->keystate) ? 0xc0 : 0x80;
1211         /* fall through */
1212     case WM_MBUTTONUP:
1213         set_input_key_state( keystate, VK_MBUTTON, down );
1214         break;
1215     case WM_RBUTTONDOWN:
1216         down = (keystate == desktop->keystate) ? 0xc0 : 0x80;
1217         /* fall through */
1218     case WM_RBUTTONUP:
1219         set_input_key_state( keystate, VK_RBUTTON, down );
1220         break;
1221     case WM_XBUTTONDOWN:
1222         down = (keystate == desktop->keystate) ? 0xc0 : 0x80;
1223         /* fall through */
1224     case WM_XBUTTONUP:
1225         if (msg->wparam >> 16 == XBUTTON1) set_input_key_state( keystate, VK_XBUTTON1, down );
1226         else if (msg->wparam >> 16 == XBUTTON2) set_input_key_state( keystate, VK_XBUTTON2, down );
1227         break;
1228     case WM_KEYDOWN:
1229     case WM_SYSKEYDOWN:
1230         down = (keystate == desktop->keystate) ? 0xc0 : 0x80;
1231         /* fall through */
1232     case WM_KEYUP:
1233     case WM_SYSKEYUP:
1234         key = (unsigned char)msg->wparam;
1235         set_input_key_state( keystate, key, down );
1236         switch(key)
1237         {
1238         case VK_LCONTROL:
1239         case VK_RCONTROL:
1240             down = (keystate[VK_LCONTROL] | keystate[VK_RCONTROL]) & 0x80;
1241             set_input_key_state( keystate, VK_CONTROL, down );
1242             break;
1243         case VK_LMENU:
1244         case VK_RMENU:
1245             down = (keystate[VK_LMENU] | keystate[VK_RMENU]) & 0x80;
1246             set_input_key_state( keystate, VK_MENU, down );
1247             break;
1248         case VK_LSHIFT:
1249         case VK_RSHIFT:
1250             down = (keystate[VK_LSHIFT] | keystate[VK_RSHIFT]) & 0x80;
1251             set_input_key_state( keystate, VK_SHIFT, down );
1252             break;
1253         }
1254         break;
1255     }
1256 }
1257
1258 /* release the hardware message currently being processed by the given thread */
1259 static void release_hardware_message( struct msg_queue *queue, unsigned int hw_id,
1260                                       int remove, user_handle_t new_win )
1261 {
1262     struct thread_input *input = queue->input;
1263     struct message *msg;
1264
1265     LIST_FOR_EACH_ENTRY( msg, &input->msg_list, struct message, entry )
1266     {
1267         if (msg->unique_id == hw_id) break;
1268     }
1269     if (&msg->entry == &input->msg_list) return;  /* not found */
1270
1271     /* clear the queue bit for that message */
1272     if (remove || new_win)
1273     {
1274         struct message *other;
1275         int clr_bit;
1276
1277         clr_bit = get_hardware_msg_bit( msg );
1278         LIST_FOR_EACH_ENTRY( other, &input->msg_list, struct message, entry )
1279         {
1280             if (other != msg && get_hardware_msg_bit( other ) == clr_bit)
1281             {
1282                 clr_bit = 0;
1283                 break;
1284             }
1285         }
1286         if (clr_bit) clear_queue_bits( queue, clr_bit );
1287     }
1288
1289     if (new_win)  /* set the new window */
1290     {
1291         struct thread *owner = get_window_thread( new_win );
1292         if (owner)
1293         {
1294             msg->win = new_win;
1295             if (owner->queue->input != input)
1296             {
1297                 list_remove( &msg->entry );
1298                 if (merge_message( owner->queue->input, msg ))
1299                 {
1300                     free_message( msg );
1301                     release_object( owner );
1302                     return;
1303                 }
1304                 list_add_tail( &owner->queue->input->msg_list, &msg->entry );
1305             }
1306             set_queue_bits( owner->queue, get_hardware_msg_bit( msg ));
1307             remove = 0;
1308             release_object( owner );
1309         }
1310     }
1311     if (remove)
1312     {
1313         update_input_key_state( input->desktop, input->keystate, msg );
1314         list_remove( &msg->entry );
1315         free_message( msg );
1316     }
1317 }
1318
1319 static int queue_hotkey_message( struct desktop *desktop, struct message *msg )
1320 {
1321     struct hotkey *hotkey;
1322     unsigned int modifiers = 0;
1323
1324     if (msg->msg != WM_KEYDOWN) return 0;
1325
1326     if (desktop->keystate[VK_MENU] & 0x80) modifiers |= MOD_ALT;
1327     if (desktop->keystate[VK_CONTROL] & 0x80) modifiers |= MOD_CONTROL;
1328     if (desktop->keystate[VK_SHIFT] & 0x80) modifiers |= MOD_SHIFT;
1329     if ((desktop->keystate[VK_LWIN] & 0x80) || (desktop->keystate[VK_RWIN] & 0x80)) modifiers |= MOD_WIN;
1330
1331     LIST_FOR_EACH_ENTRY( hotkey, &desktop->hotkeys, struct hotkey, entry )
1332     {
1333         if (hotkey->vkey != msg->wparam) continue;
1334         if ((hotkey->flags & (MOD_ALT|MOD_CONTROL|MOD_SHIFT|MOD_WIN)) == modifiers) goto found;
1335     }
1336
1337     return 0;
1338
1339 found:
1340     msg->type      = MSG_POSTED;
1341     msg->win       = hotkey->win;
1342     msg->msg       = WM_HOTKEY;
1343     msg->wparam    = hotkey->id;
1344     msg->lparam    = ((hotkey->vkey & 0xffff) << 16) | modifiers;
1345
1346     free( msg->data );
1347     msg->data      = NULL;
1348     msg->data_size = 0;
1349
1350     list_add_tail( &hotkey->queue->msg_list[POST_MESSAGE], &msg->entry );
1351     set_queue_bits( hotkey->queue, QS_POSTMESSAGE|QS_ALLPOSTMESSAGE );
1352     return 1;
1353 }
1354
1355 /* find the window that should receive a given hardware message */
1356 static user_handle_t find_hardware_message_window( struct desktop *desktop, struct thread_input *input,
1357                                                    struct message *msg, unsigned int *msg_code )
1358 {
1359     struct hardware_msg_data *data = msg->data;
1360     user_handle_t win = 0;
1361
1362     *msg_code = msg->msg;
1363     if (is_keyboard_msg( msg ))
1364     {
1365         if (input && !(win = input->focus))
1366         {
1367             win = input->active;
1368             if (*msg_code < WM_SYSKEYDOWN) *msg_code += WM_SYSKEYDOWN - WM_KEYDOWN;
1369         }
1370     }
1371     else  /* mouse message */
1372     {
1373         if (!input || !(win = input->capture))
1374         {
1375             if (!(win = msg->win) || !is_window_visible( win ) || is_window_transparent( win ))
1376                 win = window_from_point( desktop, data->x, data->y );
1377         }
1378     }
1379     return win;
1380 }
1381
1382 /* queue a hardware message into a given thread input */
1383 static void queue_hardware_message( struct desktop *desktop, struct message *msg, int always_queue )
1384 {
1385     user_handle_t win;
1386     struct thread *thread;
1387     struct thread_input *input;
1388     unsigned int msg_code;
1389     struct hardware_msg_data *data = msg->data;
1390
1391     update_input_key_state( desktop, desktop->keystate, msg );
1392     last_input_time = get_tick_count();
1393     if (msg->msg != WM_MOUSEMOVE) always_queue = 1;
1394
1395     if (is_keyboard_msg( msg ))
1396     {
1397         if (queue_hotkey_message( desktop, msg )) return;
1398         if (desktop->keystate[VK_MENU] & 0x80) msg->lparam |= KF_ALTDOWN << 16;
1399         if (msg->wparam == VK_SHIFT || msg->wparam == VK_LSHIFT || msg->wparam == VK_RSHIFT)
1400             msg->lparam &= ~(KF_EXTENDED << 16);
1401     }
1402     else
1403     {
1404         if (msg->msg == WM_MOUSEMOVE)
1405         {
1406             int x = min( max( data->x, desktop->cursor.clip.left ), desktop->cursor.clip.right-1 );
1407             int y = min( max( data->y, desktop->cursor.clip.top ), desktop->cursor.clip.bottom-1 );
1408             if (desktop->cursor.x != x || desktop->cursor.y != y) always_queue = 1;
1409             desktop->cursor.x = x;
1410             desktop->cursor.y = y;
1411             desktop->cursor.last_change = get_tick_count();
1412         }
1413         if (desktop->keystate[VK_LBUTTON] & 0x80)  msg->wparam |= MK_LBUTTON;
1414         if (desktop->keystate[VK_MBUTTON] & 0x80)  msg->wparam |= MK_MBUTTON;
1415         if (desktop->keystate[VK_RBUTTON] & 0x80)  msg->wparam |= MK_RBUTTON;
1416         if (desktop->keystate[VK_SHIFT] & 0x80)    msg->wparam |= MK_SHIFT;
1417         if (desktop->keystate[VK_CONTROL] & 0x80)  msg->wparam |= MK_CONTROL;
1418         if (desktop->keystate[VK_XBUTTON1] & 0x80) msg->wparam |= MK_XBUTTON1;
1419         if (desktop->keystate[VK_XBUTTON2] & 0x80) msg->wparam |= MK_XBUTTON2;
1420     }
1421     data->x = desktop->cursor.x;
1422     data->y = desktop->cursor.y;
1423
1424     if (msg->win && (thread = get_window_thread( msg->win )))
1425     {
1426         input = thread->queue->input;
1427         release_object( thread );
1428     }
1429     else input = desktop->foreground_input;
1430
1431     win = find_hardware_message_window( desktop, input, msg, &msg_code );
1432     if (!win || !(thread = get_window_thread(win)))
1433     {
1434         if (input) update_input_key_state( input->desktop, input->keystate, msg );
1435         free_message( msg );
1436         return;
1437     }
1438     input = thread->queue->input;
1439
1440     if (win != desktop->cursor.win) always_queue = 1;
1441     desktop->cursor.win = win;
1442
1443     if (!always_queue || merge_message( input, msg )) free_message( msg );
1444     else
1445     {
1446         msg->unique_id = 0;  /* will be set once we return it to the app */
1447         list_add_tail( &input->msg_list, &msg->entry );
1448         set_queue_bits( thread->queue, get_hardware_msg_bit(msg) );
1449     }
1450     release_object( thread );
1451 }
1452
1453 /* send the low-level hook message for a given hardware message */
1454 static int send_hook_ll_message( struct desktop *desktop, struct message *hardware_msg,
1455                                  const hw_input_t *input, struct msg_queue *sender )
1456 {
1457     struct thread *hook_thread;
1458     struct msg_queue *queue;
1459     struct message *msg;
1460     timeout_t timeout = 2000 * -10000;  /* FIXME: load from registry */
1461     int id = (input->type == INPUT_MOUSE) ? WH_MOUSE_LL : WH_KEYBOARD_LL;
1462
1463     if (!(hook_thread = get_first_global_hook( id ))) return 0;
1464     if (!(queue = hook_thread->queue)) return 0;
1465     if (is_queue_hung( queue )) return 0;
1466
1467     if (!(msg = mem_alloc( sizeof(*msg) ))) return 0;
1468
1469     msg->type      = MSG_HOOK_LL;
1470     msg->win       = 0;
1471     msg->msg       = id;
1472     msg->wparam    = hardware_msg->msg;
1473     msg->time      = hardware_msg->time;
1474     msg->data_size = hardware_msg->data_size;
1475     msg->result    = NULL;
1476
1477     if (input->type == INPUT_KEYBOARD)
1478     {
1479         unsigned short vkey = input->kbd.vkey;
1480         if (input->kbd.flags & KEYEVENTF_UNICODE) vkey = VK_PACKET;
1481         msg->lparam = (input->kbd.scan << 16) | vkey;
1482     }
1483     else msg->lparam = input->mouse.data << 16;
1484
1485     if (!(msg->data = memdup( hardware_msg->data, hardware_msg->data_size )) ||
1486         !(msg->result = alloc_message_result( sender, queue, msg, timeout )))
1487     {
1488         free_message( msg );
1489         return 0;
1490     }
1491     msg->result->hardware_msg = hardware_msg;
1492     msg->result->desktop = (struct desktop *)grab_object( desktop );
1493     list_add_tail( &queue->msg_list[SEND_MESSAGE], &msg->entry );
1494     set_queue_bits( queue, QS_SENDMESSAGE );
1495     return 1;
1496 }
1497
1498 /* queue a hardware message for a mouse event */
1499 static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input,
1500                                 unsigned int hook_flags, struct msg_queue *sender )
1501 {
1502     struct hardware_msg_data *msg_data;
1503     struct message *msg;
1504     unsigned int i, time, flags;
1505     int wait = 0, x, y;
1506
1507     static const unsigned int messages[] =
1508     {
1509         WM_MOUSEMOVE,    /* 0x0001 = MOUSEEVENTF_MOVE */
1510         WM_LBUTTONDOWN,  /* 0x0002 = MOUSEEVENTF_LEFTDOWN */
1511         WM_LBUTTONUP,    /* 0x0004 = MOUSEEVENTF_LEFTUP */
1512         WM_RBUTTONDOWN,  /* 0x0008 = MOUSEEVENTF_RIGHTDOWN */
1513         WM_RBUTTONUP,    /* 0x0010 = MOUSEEVENTF_RIGHTUP */
1514         WM_MBUTTONDOWN,  /* 0x0020 = MOUSEEVENTF_MIDDLEDOWN */
1515         WM_MBUTTONUP,    /* 0x0040 = MOUSEEVENTF_MIDDLEUP */
1516         WM_XBUTTONDOWN,  /* 0x0080 = MOUSEEVENTF_XDOWN */
1517         WM_XBUTTONUP,    /* 0x0100 = MOUSEEVENTF_XUP */
1518         0,               /* 0x0200 = unused */
1519         0,               /* 0x0400 = unused */
1520         WM_MOUSEWHEEL,   /* 0x0800 = MOUSEEVENTF_WHEEL */
1521         WM_MOUSEHWHEEL   /* 0x1000 = MOUSEEVENTF_HWHEEL */
1522     };
1523
1524     desktop->cursor.last_change = get_tick_count();
1525     flags = input->mouse.flags;
1526     time  = input->mouse.time;
1527     if (!time) time = desktop->cursor.last_change;
1528
1529     if (flags & MOUSEEVENTF_MOVE)
1530     {
1531         if (flags & MOUSEEVENTF_ABSOLUTE)
1532         {
1533             x = input->mouse.x;
1534             y = input->mouse.y;
1535             if (flags & ~(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE) &&
1536                 x == desktop->cursor.x && y == desktop->cursor.y)
1537                 flags &= ~MOUSEEVENTF_MOVE;
1538         }
1539         else
1540         {
1541             x = desktop->cursor.x + input->mouse.x;
1542             y = desktop->cursor.y + input->mouse.y;
1543         }
1544     }
1545     else
1546     {
1547         x = desktop->cursor.x;
1548         y = desktop->cursor.y;
1549     }
1550
1551     for (i = 0; i < sizeof(messages)/sizeof(messages[0]); i++)
1552     {
1553         if (!messages[i]) continue;
1554         if (!(flags & (1 << i))) continue;
1555         flags &= ~(1 << i);
1556
1557         if (!(msg = mem_alloc( sizeof(*msg) ))) return 0;
1558         if (!(msg_data = mem_alloc( sizeof(*msg_data) )))
1559         {
1560             free( msg );
1561             return 0;
1562         }
1563         memset( msg_data, 0, sizeof(*msg_data) );
1564
1565         msg->type      = MSG_HARDWARE;
1566         msg->win       = get_user_full_handle( win );
1567         msg->msg       = messages[i];
1568         msg->wparam    = input->mouse.data << 16;
1569         msg->lparam    = 0;
1570         msg->time      = time;
1571         msg->result    = NULL;
1572         msg->data      = msg_data;
1573         msg->data_size = sizeof(*msg_data);
1574         msg_data->x    = x;
1575         msg_data->y    = y;
1576         msg_data->info = input->mouse.info;
1577         if (hook_flags & SEND_HWMSG_INJECTED) msg_data->flags = LLMHF_INJECTED;
1578
1579         /* specify a sender only when sending the last message */
1580         if (!(flags & ((1 << sizeof(messages)/sizeof(messages[0])) - 1)))
1581         {
1582             if (!(wait = send_hook_ll_message( desktop, msg, input, sender )))
1583                 queue_hardware_message( desktop, msg, 0 );
1584         }
1585         else if (!send_hook_ll_message( desktop, msg, input, NULL ))
1586             queue_hardware_message( desktop, msg, 0 );
1587     }
1588     return wait;
1589 }
1590
1591 /* queue a hardware message for a keyboard event */
1592 static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input,
1593                                    unsigned int hook_flags, struct msg_queue *sender )
1594 {
1595     struct hardware_msg_data *msg_data;
1596     struct message *msg;
1597     unsigned char vkey = input->kbd.vkey;
1598     int wait;
1599
1600     if (!(msg = mem_alloc( sizeof(*msg) ))) return 0;
1601     if (!(msg_data = mem_alloc( sizeof(*msg_data) )))
1602     {
1603         free( msg );
1604         return 0;
1605     }
1606     memset( msg_data, 0, sizeof(*msg_data) );
1607
1608     msg->type      = MSG_HARDWARE;
1609     msg->win       = get_user_full_handle( win );
1610     msg->lparam    = (input->kbd.scan << 16) | 1; /* repeat count */
1611     msg->time      = input->kbd.time;
1612     msg->result    = NULL;
1613     msg->data      = msg_data;
1614     msg->data_size = sizeof(*msg_data);
1615     msg_data->info = input->kbd.info;
1616     if (!msg->time) msg->time = get_tick_count();
1617     if (hook_flags & SEND_HWMSG_INJECTED) msg_data->flags = LLKHF_INJECTED;
1618
1619     if (input->kbd.flags & KEYEVENTF_UNICODE)
1620     {
1621         msg->wparam = VK_PACKET;
1622     }
1623     else
1624     {
1625         unsigned int flags = 0;
1626         switch (vkey)
1627         {
1628         case VK_MENU:
1629         case VK_LMENU:
1630         case VK_RMENU:
1631             vkey = (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) ? VK_RMENU : VK_LMENU;
1632             break;
1633         case VK_CONTROL:
1634         case VK_LCONTROL:
1635         case VK_RCONTROL:
1636             vkey = (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) ? VK_RCONTROL : VK_LCONTROL;
1637             break;
1638         case VK_SHIFT:
1639         case VK_LSHIFT:
1640         case VK_RSHIFT:
1641             vkey = (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) ? VK_RSHIFT : VK_LSHIFT;
1642             break;
1643         }
1644         if (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) flags |= KF_EXTENDED;
1645         /* FIXME: set KF_DLGMODE and KF_MENUMODE when needed */
1646         if (input->kbd.flags & KEYEVENTF_KEYUP) flags |= KF_REPEAT | KF_UP;
1647         else if (desktop->keystate[vkey] & 0x80) flags |= KF_REPEAT;
1648
1649         msg->wparam = vkey;
1650         msg->lparam |= flags << 16;
1651         msg_data->flags |= (flags & (KF_EXTENDED | KF_ALTDOWN | KF_UP)) >> 8;
1652     }
1653
1654     msg->msg = (input->kbd.flags & KEYEVENTF_KEYUP) ? WM_KEYUP : WM_KEYDOWN;
1655
1656     switch (vkey)
1657     {
1658     case VK_LMENU:
1659     case VK_RMENU:
1660         if (input->kbd.flags & KEYEVENTF_KEYUP)
1661         {
1662             /* send WM_SYSKEYUP if Alt still pressed and no other key in between */
1663             /* we use 0x02 as a flag to track if some other SYSKEYUP was sent already */
1664             if ((desktop->keystate[VK_MENU] & 0x82) != 0x82) break;
1665             msg->msg = WM_SYSKEYUP;
1666             desktop->keystate[VK_MENU] &= ~0x02;
1667         }
1668         else
1669         {
1670             /* send WM_SYSKEYDOWN for Alt except with Ctrl */
1671             if (desktop->keystate[VK_CONTROL] & 0x80) break;
1672             msg->msg = WM_SYSKEYDOWN;
1673             desktop->keystate[VK_MENU] |= 0x02;
1674         }
1675         break;
1676
1677     case VK_LCONTROL:
1678     case VK_RCONTROL:
1679         /* send WM_SYSKEYUP on release if Alt still pressed */
1680         if (!(input->kbd.flags & KEYEVENTF_KEYUP)) break;
1681         if (!(desktop->keystate[VK_MENU] & 0x80)) break;
1682         msg->msg = WM_SYSKEYUP;
1683         desktop->keystate[VK_MENU] &= ~0x02;
1684         break;
1685
1686     default:
1687         /* send WM_SYSKEY for Alt-anykey and for F10 */
1688         if (desktop->keystate[VK_CONTROL] & 0x80) break;
1689         if (!(desktop->keystate[VK_MENU] & 0x80)) break;
1690         /* fall through */
1691     case VK_F10:
1692         msg->msg = (input->kbd.flags & KEYEVENTF_KEYUP) ? WM_SYSKEYUP : WM_SYSKEYDOWN;
1693         desktop->keystate[VK_MENU] &= ~0x02;
1694         break;
1695     }
1696     if (!(wait = send_hook_ll_message( desktop, msg, input, sender )))
1697         queue_hardware_message( desktop, msg, 1 );
1698
1699     return wait;
1700 }
1701
1702 /* queue a hardware message for a custom type of event */
1703 static void queue_custom_hardware_message( struct desktop *desktop, user_handle_t win,
1704                                            const hw_input_t *input )
1705 {
1706     struct hardware_msg_data *msg_data;
1707     struct message *msg;
1708
1709     if (!(msg = mem_alloc( sizeof(*msg) ))) return;
1710     if (!(msg_data = mem_alloc( sizeof(*msg_data) )))
1711     {
1712         free( msg );
1713         return;
1714     }
1715     memset( msg_data, 0, sizeof(*msg_data) );
1716
1717     msg->type      = MSG_HARDWARE;
1718     msg->win       = get_user_full_handle( win );
1719     msg->msg       = input->hw.msg;
1720     msg->wparam    = 0;
1721     msg->lparam    = input->hw.lparam;
1722     msg->time      = get_tick_count();
1723     msg->result    = NULL;
1724     msg->data      = msg_data;
1725     msg->data_size = sizeof(*msg_data);
1726
1727     queue_hardware_message( desktop, msg, 1 );
1728 }
1729
1730 /* check message filter for a hardware message */
1731 static int check_hw_message_filter( user_handle_t win, unsigned int msg_code,
1732                                     user_handle_t filter_win, unsigned int first, unsigned int last )
1733 {
1734     if (msg_code >= WM_KEYFIRST && msg_code <= WM_KEYLAST)
1735     {
1736         /* we can only test the window for a keyboard message since the
1737          * dest window for a mouse message depends on hittest */
1738         if (filter_win && win != filter_win && !is_child_window( filter_win, win ))
1739             return 0;
1740         /* the message code is final for a keyboard message, we can simply check it */
1741         return check_msg_filter( msg_code, first, last );
1742     }
1743     else  /* mouse message */
1744     {
1745         /* we need to check all possible values that the message can have in the end */
1746
1747         if (check_msg_filter( msg_code, first, last )) return 1;
1748         if (msg_code == WM_MOUSEWHEEL) return 0;  /* no other possible value for this one */
1749
1750         /* all other messages can become non-client messages */
1751         if (check_msg_filter( msg_code + (WM_NCMOUSEFIRST - WM_MOUSEFIRST), first, last )) return 1;
1752
1753         /* clicks can become double-clicks or non-client double-clicks */
1754         if (msg_code == WM_LBUTTONDOWN || msg_code == WM_MBUTTONDOWN ||
1755             msg_code == WM_RBUTTONDOWN || msg_code == WM_XBUTTONDOWN)
1756         {
1757             if (check_msg_filter( msg_code + (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN), first, last )) return 1;
1758             if (check_msg_filter( msg_code + (WM_NCLBUTTONDBLCLK - WM_LBUTTONDOWN), first, last )) return 1;
1759         }
1760         return 0;
1761     }
1762 }
1763
1764
1765 /* find a hardware message for the given queue */
1766 static int get_hardware_message( struct thread *thread, unsigned int hw_id, user_handle_t filter_win,
1767                                  unsigned int first, unsigned int last, struct get_message_reply *reply )
1768 {
1769     struct thread_input *input = thread->queue->input;
1770     struct thread *win_thread;
1771     struct list *ptr;
1772     user_handle_t win;
1773     int clear_bits, got_one = 0;
1774     unsigned int msg_code;
1775
1776     ptr = list_head( &input->msg_list );
1777     if (hw_id)
1778     {
1779         while (ptr)
1780         {
1781             struct message *msg = LIST_ENTRY( ptr, struct message, entry );
1782             if (msg->unique_id == hw_id) break;
1783             ptr = list_next( &input->msg_list, ptr );
1784         }
1785         if (!ptr) ptr = list_head( &input->msg_list );
1786         else ptr = list_next( &input->msg_list, ptr );  /* start from the next one */
1787     }
1788
1789     if (ptr == list_head( &input->msg_list ))
1790         clear_bits = QS_KEY | QS_MOUSEMOVE | QS_MOUSEBUTTON;
1791     else
1792         clear_bits = 0;  /* don't clear bits if we don't go through the whole list */
1793
1794     while (ptr)
1795     {
1796         struct message *msg = LIST_ENTRY( ptr, struct message, entry );
1797         struct hardware_msg_data *data = msg->data;
1798
1799         ptr = list_next( &input->msg_list, ptr );
1800         win = find_hardware_message_window( input->desktop, input, msg, &msg_code );
1801         if (!win || !(win_thread = get_window_thread( win )))
1802         {
1803             /* no window at all, remove it */
1804             update_input_key_state( input->desktop, input->keystate, msg );
1805             list_remove( &msg->entry );
1806             free_message( msg );
1807             continue;
1808         }
1809         if (win_thread != thread)
1810         {
1811             if (win_thread->queue->input == input)
1812             {
1813                 /* wake the other thread */
1814                 set_queue_bits( win_thread->queue, get_hardware_msg_bit(msg) );
1815                 got_one = 1;
1816             }
1817             else
1818             {
1819                 /* for another thread input, drop it */
1820                 update_input_key_state( input->desktop, input->keystate, msg );
1821                 list_remove( &msg->entry );
1822                 free_message( msg );
1823             }
1824             release_object( win_thread );
1825             continue;
1826         }
1827         release_object( win_thread );
1828
1829         /* if we already got a message for another thread, or if it doesn't
1830          * match the filter we skip it */
1831         if (got_one || !check_hw_message_filter( win, msg_code, filter_win, first, last ))
1832         {
1833             clear_bits &= ~get_hardware_msg_bit( msg );
1834             continue;
1835         }
1836         /* now we can return it */
1837         if (!msg->unique_id) msg->unique_id = get_unique_id();
1838         reply->type   = MSG_HARDWARE;
1839         reply->win    = win;
1840         reply->msg    = msg_code;
1841         reply->wparam = msg->wparam;
1842         reply->lparam = msg->lparam;
1843         reply->time   = msg->time;
1844
1845         data->hw_id = msg->unique_id;
1846         set_reply_data( msg->data, msg->data_size );
1847         return 1;
1848     }
1849     /* nothing found, clear the hardware queue bits */
1850     clear_queue_bits( thread->queue, clear_bits );
1851     return 0;
1852 }
1853
1854 /* increment (or decrement if 'incr' is negative) the queue paint count */
1855 void inc_queue_paint_count( struct thread *thread, int incr )
1856 {
1857     struct msg_queue *queue = thread->queue;
1858
1859     assert( queue );
1860
1861     if ((queue->paint_count += incr) < 0) queue->paint_count = 0;
1862
1863     if (queue->paint_count)
1864         set_queue_bits( queue, QS_PAINT );
1865     else
1866         clear_queue_bits( queue, QS_PAINT );
1867 }
1868
1869
1870 /* remove all messages and timers belonging to a certain window */
1871 void queue_cleanup_window( struct thread *thread, user_handle_t win )
1872 {
1873     struct msg_queue *queue = thread->queue;
1874     struct list *ptr;
1875     int i;
1876
1877     if (!queue) return;
1878
1879     /* remove timers */
1880
1881     ptr = list_head( &queue->pending_timers );
1882     while (ptr)
1883     {
1884         struct list *next = list_next( &queue->pending_timers, ptr );
1885         struct timer *timer = LIST_ENTRY( ptr, struct timer, entry );
1886         if (timer->win == win) free_timer( queue, timer );
1887         ptr = next;
1888     }
1889     ptr = list_head( &queue->expired_timers );
1890     while (ptr)
1891     {
1892         struct list *next = list_next( &queue->expired_timers, ptr );
1893         struct timer *timer = LIST_ENTRY( ptr, struct timer, entry );
1894         if (timer->win == win) free_timer( queue, timer );
1895         ptr = next;
1896     }
1897
1898     /* remove messages */
1899     for (i = 0; i < NB_MSG_KINDS; i++)
1900     {
1901         struct list *ptr, *next;
1902
1903         LIST_FOR_EACH_SAFE( ptr, next, &queue->msg_list[i] )
1904         {
1905             struct message *msg = LIST_ENTRY( ptr, struct message, entry );
1906             if (msg->win == win) remove_queue_message( queue, msg, i );
1907         }
1908     }
1909
1910     thread_input_cleanup_window( queue, win );
1911 }
1912
1913 /* post a message to a window; used by socket handling */
1914 void post_message( user_handle_t win, unsigned int message, lparam_t wparam, lparam_t lparam )
1915 {
1916     struct message *msg;
1917     struct thread *thread = get_window_thread( win );
1918
1919     if (!thread) return;
1920
1921     if (thread->queue && (msg = mem_alloc( sizeof(*msg) )))
1922     {
1923         msg->type      = MSG_POSTED;
1924         msg->win       = get_user_full_handle( win );
1925         msg->msg       = message;
1926         msg->wparam    = wparam;
1927         msg->lparam    = lparam;
1928         msg->time      = get_tick_count();
1929         msg->result    = NULL;
1930         msg->data      = NULL;
1931         msg->data_size = 0;
1932
1933         list_add_tail( &thread->queue->msg_list[POST_MESSAGE], &msg->entry );
1934         set_queue_bits( thread->queue, QS_POSTMESSAGE|QS_ALLPOSTMESSAGE );
1935     }
1936     release_object( thread );
1937 }
1938
1939 /* post a win event */
1940 void post_win_event( struct thread *thread, unsigned int event,
1941                      user_handle_t win, unsigned int object_id,
1942                      unsigned int child_id, client_ptr_t hook_proc,
1943                      const WCHAR *module, data_size_t module_size,
1944                      user_handle_t hook)
1945 {
1946     struct message *msg;
1947
1948     if (thread->queue && (msg = mem_alloc( sizeof(*msg) )))
1949     {
1950         struct winevent_msg_data *data;
1951
1952         msg->type      = MSG_WINEVENT;
1953         msg->win       = get_user_full_handle( win );
1954         msg->msg       = event;
1955         msg->wparam    = object_id;
1956         msg->lparam    = child_id;
1957         msg->time      = get_tick_count();
1958         msg->result    = NULL;
1959
1960         if ((data = malloc( sizeof(*data) + module_size )))
1961         {
1962             data->hook = hook;
1963             data->tid  = get_thread_id( current );
1964             data->hook_proc = hook_proc;
1965             memcpy( data + 1, module, module_size );
1966
1967             msg->data = data;
1968             msg->data_size = sizeof(*data) + module_size;
1969
1970             if (debug_level > 1)
1971                 fprintf( stderr, "post_win_event: tid %04x event %04x win %08x object_id %d child_id %d\n",
1972                          get_thread_id(thread), event, win, object_id, child_id );
1973             list_add_tail( &thread->queue->msg_list[SEND_MESSAGE], &msg->entry );
1974             set_queue_bits( thread->queue, QS_SENDMESSAGE );
1975         }
1976         else
1977             free( msg );
1978     }
1979 }
1980
1981 /* free all hotkeys on a desktop, optionally filtering by window */
1982 void free_hotkeys( struct desktop *desktop, user_handle_t window )
1983 {
1984     struct hotkey *hotkey, *hotkey2;
1985
1986     LIST_FOR_EACH_ENTRY_SAFE( hotkey, hotkey2, &desktop->hotkeys, struct hotkey, entry )
1987     {
1988         if (!window || hotkey->win == window)
1989         {
1990             list_remove( &hotkey->entry );
1991             free( hotkey );
1992         }
1993     }
1994 }
1995
1996
1997 /* check if the thread owning the window is hung */
1998 DECL_HANDLER(is_window_hung)
1999 {
2000     struct thread *thread;
2001
2002     thread = get_window_thread( req->win );
2003     if (thread)
2004     {
2005         reply->is_hung = is_queue_hung( thread->queue );
2006         release_object( thread );
2007     }
2008     else reply->is_hung = 0;
2009 }
2010
2011
2012 /* get the message queue of the current thread */
2013 DECL_HANDLER(get_msg_queue)
2014 {
2015     struct msg_queue *queue = get_current_queue();
2016
2017     reply->handle = 0;
2018     if (queue) reply->handle = alloc_handle( current->process, queue, SYNCHRONIZE, 0 );
2019 }
2020
2021
2022 /* set the file descriptor associated to the current thread queue */
2023 DECL_HANDLER(set_queue_fd)
2024 {
2025     struct msg_queue *queue = get_current_queue();
2026     struct file *file;
2027     int unix_fd;
2028
2029     if (queue->fd)  /* fd can only be set once */
2030     {
2031         set_error( STATUS_ACCESS_DENIED );
2032         return;
2033     }
2034     if (!(file = get_file_obj( current->process, req->handle, SYNCHRONIZE ))) return;
2035
2036     if ((unix_fd = get_file_unix_fd( file )) != -1)
2037     {
2038         if ((unix_fd = dup( unix_fd )) != -1)
2039             queue->fd = create_anonymous_fd( &msg_queue_fd_ops, unix_fd, &queue->obj, 0 );
2040         else
2041             file_set_error();
2042     }
2043     release_object( file );
2044 }
2045
2046
2047 /* set the current message queue wakeup mask */
2048 DECL_HANDLER(set_queue_mask)
2049 {
2050     struct msg_queue *queue = get_current_queue();
2051
2052     if (queue)
2053     {
2054         queue->wake_mask    = req->wake_mask;
2055         queue->changed_mask = req->changed_mask;
2056         reply->wake_bits    = queue->wake_bits;
2057         reply->changed_bits = queue->changed_bits;
2058         if (is_signaled( queue ))
2059         {
2060             /* if skip wait is set, do what would have been done in the subsequent wait */
2061             if (req->skip_wait) msg_queue_satisfied( &queue->obj, current );
2062             else wake_up( &queue->obj, 0 );
2063         }
2064     }
2065 }
2066
2067
2068 /* get the current message queue status */
2069 DECL_HANDLER(get_queue_status)
2070 {
2071     struct msg_queue *queue = current->queue;
2072     if (queue)
2073     {
2074         reply->wake_bits    = queue->wake_bits;
2075         reply->changed_bits = queue->changed_bits;
2076         if (req->clear) queue->changed_bits = 0;
2077     }
2078     else reply->wake_bits = reply->changed_bits = 0;
2079 }
2080
2081
2082 /* send a message to a thread queue */
2083 DECL_HANDLER(send_message)
2084 {
2085     struct message *msg;
2086     struct msg_queue *send_queue = get_current_queue();
2087     struct msg_queue *recv_queue = NULL;
2088     struct thread *thread = NULL;
2089
2090     if (!(thread = get_thread_from_id( req->id ))) return;
2091
2092     if (!(recv_queue = thread->queue))
2093     {
2094         set_error( STATUS_INVALID_PARAMETER );
2095         release_object( thread );
2096         return;
2097     }
2098     if ((req->flags & SEND_MSG_ABORT_IF_HUNG) && is_queue_hung(recv_queue))
2099     {
2100         set_error( STATUS_TIMEOUT );
2101         release_object( thread );
2102         return;
2103     }
2104
2105     if ((msg = mem_alloc( sizeof(*msg) )))
2106     {
2107         msg->type      = req->type;
2108         msg->win       = get_user_full_handle( req->win );
2109         msg->msg       = req->msg;
2110         msg->wparam    = req->wparam;
2111         msg->lparam    = req->lparam;
2112         msg->time      = get_tick_count();
2113         msg->result    = NULL;
2114         msg->data      = NULL;
2115         msg->data_size = get_req_data_size();
2116
2117         if (msg->data_size && !(msg->data = memdup( get_req_data(), msg->data_size )))
2118         {
2119             free( msg );
2120             release_object( thread );
2121             return;
2122         }
2123
2124         switch(msg->type)
2125         {
2126         case MSG_OTHER_PROCESS:
2127         case MSG_ASCII:
2128         case MSG_UNICODE:
2129         case MSG_CALLBACK:
2130             if (!(msg->result = alloc_message_result( send_queue, recv_queue, msg, req->timeout )))
2131             {
2132                 free_message( msg );
2133                 break;
2134             }
2135             /* fall through */
2136         case MSG_NOTIFY:
2137             list_add_tail( &recv_queue->msg_list[SEND_MESSAGE], &msg->entry );
2138             set_queue_bits( recv_queue, QS_SENDMESSAGE );
2139             break;
2140         case MSG_POSTED:
2141             list_add_tail( &recv_queue->msg_list[POST_MESSAGE], &msg->entry );
2142             set_queue_bits( recv_queue, QS_POSTMESSAGE|QS_ALLPOSTMESSAGE );
2143             break;
2144         case MSG_HARDWARE:  /* should use send_hardware_message instead */
2145         case MSG_CALLBACK_RESULT:  /* cannot send this one */
2146         case MSG_HOOK_LL:  /* generated internally */
2147         default:
2148             set_error( STATUS_INVALID_PARAMETER );
2149             free( msg );
2150             break;
2151         }
2152     }
2153     release_object( thread );
2154 }
2155
2156 /* send a hardware message to a thread queue */
2157 DECL_HANDLER(send_hardware_message)
2158 {
2159     struct thread *thread = NULL;
2160     struct desktop *desktop;
2161     struct msg_queue *sender = get_current_queue();
2162
2163     if (req->win)
2164     {
2165         if (!(thread = get_window_thread( req->win ))) return;
2166         desktop = (struct desktop *)grab_object( thread->queue->input->desktop );
2167     }
2168     else if (!(desktop = get_thread_desktop( current, 0 ))) return;
2169
2170     switch (req->input.type)
2171     {
2172     case INPUT_MOUSE:
2173         reply->wait = queue_mouse_message( desktop, req->win, &req->input, req->flags, sender );
2174         break;
2175     case INPUT_KEYBOARD:
2176         reply->wait = queue_keyboard_message( desktop, req->win, &req->input, req->flags, sender );
2177         break;
2178     case INPUT_HARDWARE:
2179         queue_custom_hardware_message( desktop, req->win, &req->input );
2180         break;
2181     default:
2182         set_error( STATUS_INVALID_PARAMETER );
2183     }
2184     if (thread) release_object( thread );
2185     release_object( desktop );
2186 }
2187
2188 /* post a quit message to the current queue */
2189 DECL_HANDLER(post_quit_message)
2190 {
2191     struct msg_queue *queue = get_current_queue();
2192
2193     if (!queue)
2194         return;
2195
2196     queue->quit_message = 1;
2197     queue->exit_code = req->exit_code;
2198     set_queue_bits( queue, QS_POSTMESSAGE|QS_ALLPOSTMESSAGE );
2199 }
2200
2201 /* get a message from the current queue */
2202 DECL_HANDLER(get_message)
2203 {
2204     struct timer *timer;
2205     struct list *ptr;
2206     struct msg_queue *queue = get_current_queue();
2207     user_handle_t get_win = get_user_full_handle( req->get_win );
2208     unsigned int filter = req->flags >> 16;
2209
2210     reply->active_hooks = get_active_hooks();
2211
2212     if (!queue) return;
2213     queue->last_get_msg = current_time;
2214     if (!filter) filter = QS_ALLINPUT;
2215
2216     /* first check for sent messages */
2217     if ((ptr = list_head( &queue->msg_list[SEND_MESSAGE] )))
2218     {
2219         struct message *msg = LIST_ENTRY( ptr, struct message, entry );
2220         receive_message( queue, msg, reply );
2221         return;
2222     }
2223
2224     /* clear changed bits so we can wait on them if we don't find a message */
2225     if (filter & QS_POSTMESSAGE)
2226     {
2227         queue->changed_bits &= ~(QS_POSTMESSAGE | QS_HOTKEY | QS_TIMER);
2228         if (req->get_first == 0 && req->get_last == ~0U) queue->changed_bits &= ~QS_ALLPOSTMESSAGE;
2229     }
2230     if (filter & QS_INPUT) queue->changed_bits &= ~QS_INPUT;
2231     if (filter & QS_PAINT) queue->changed_bits &= ~QS_PAINT;
2232
2233     /* then check for posted messages */
2234     if ((filter & QS_POSTMESSAGE) &&
2235         get_posted_message( queue, get_win, req->get_first, req->get_last, req->flags, reply ))
2236         return;
2237
2238     /* only check for quit messages if not posted messages pending.
2239      * note: the quit message isn't filtered */
2240     if (get_quit_message( queue, req->flags, reply ))
2241         return;
2242
2243     /* then check for any raw hardware message */
2244     if ((filter & QS_INPUT) &&
2245         filter_contains_hw_range( req->get_first, req->get_last ) &&
2246         get_hardware_message( current, req->hw_id, get_win, req->get_first, req->get_last, reply ))
2247         return;
2248
2249     /* now check for WM_PAINT */
2250     if ((filter & QS_PAINT) &&
2251         queue->paint_count &&
2252         check_msg_filter( WM_PAINT, req->get_first, req->get_last ) &&
2253         (reply->win = find_window_to_repaint( get_win, current )))
2254     {
2255         reply->type   = MSG_POSTED;
2256         reply->msg    = WM_PAINT;
2257         reply->wparam = 0;
2258         reply->lparam = 0;
2259         reply->time   = get_tick_count();
2260         return;
2261     }
2262
2263     /* now check for timer */
2264     if ((filter & QS_TIMER) &&
2265         (timer = find_expired_timer( queue, get_win, req->get_first,
2266                                      req->get_last, (req->flags & PM_REMOVE) )))
2267     {
2268         reply->type   = MSG_POSTED;
2269         reply->win    = timer->win;
2270         reply->msg    = timer->msg;
2271         reply->wparam = timer->id;
2272         reply->lparam = timer->lparam;
2273         reply->time   = get_tick_count();
2274         if (!(req->flags & PM_NOYIELD) && current->process->idle_event)
2275             set_event( current->process->idle_event );
2276         return;
2277     }
2278
2279     if (get_win == -1 && current->process->idle_event) set_event( current->process->idle_event );
2280     queue->wake_mask = req->wake_mask;
2281     queue->changed_mask = req->changed_mask;
2282     set_error( STATUS_PENDING );  /* FIXME */
2283 }
2284
2285
2286 /* reply to a sent message */
2287 DECL_HANDLER(reply_message)
2288 {
2289     if (!current->queue) set_error( STATUS_ACCESS_DENIED );
2290     else if (current->queue->recv_result)
2291         reply_message( current->queue, req->result, 0, req->remove,
2292                        get_req_data(), get_req_data_size() );
2293 }
2294
2295
2296 /* accept the current hardware message */
2297 DECL_HANDLER(accept_hardware_message)
2298 {
2299     if (current->queue)
2300         release_hardware_message( current->queue, req->hw_id, req->remove, req->new_win );
2301     else
2302         set_error( STATUS_ACCESS_DENIED );
2303 }
2304
2305
2306 /* retrieve the reply for the last message sent */
2307 DECL_HANDLER(get_message_reply)
2308 {
2309     struct message_result *result;
2310     struct list *entry;
2311     struct msg_queue *queue = current->queue;
2312
2313     if (queue)
2314     {
2315         set_error( STATUS_PENDING );
2316         reply->result = 0;
2317
2318         if (!(entry = list_head( &queue->send_result ))) return;  /* no reply ready */
2319
2320         result = LIST_ENTRY( entry, struct message_result, sender_entry );
2321         if (result->replied || req->cancel)
2322         {
2323             if (result->replied)
2324             {
2325                 reply->result = result->result;
2326                 set_error( result->error );
2327                 if (result->data)
2328                 {
2329                     data_size_t data_len = min( result->data_size, get_reply_max_size() );
2330                     set_reply_data_ptr( result->data, data_len );
2331                     result->data = NULL;
2332                     result->data_size = 0;
2333                 }
2334             }
2335             remove_result_from_sender( result );
2336
2337             entry = list_head( &queue->send_result );
2338             if (!entry) clear_queue_bits( queue, QS_SMRESULT );
2339             else
2340             {
2341                 result = LIST_ENTRY( entry, struct message_result, sender_entry );
2342                 if (!result->replied) clear_queue_bits( queue, QS_SMRESULT );
2343             }
2344         }
2345     }
2346     else set_error( STATUS_ACCESS_DENIED );
2347 }
2348
2349
2350 /* set a window timer */
2351 DECL_HANDLER(set_win_timer)
2352 {
2353     struct timer *timer;
2354     struct msg_queue *queue;
2355     struct thread *thread = NULL;
2356     user_handle_t win = 0;
2357     lparam_t id = req->id;
2358
2359     if (req->win)
2360     {
2361         if (!(win = get_user_full_handle( req->win )) || !(thread = get_window_thread( win )))
2362         {
2363             set_error( STATUS_INVALID_HANDLE );
2364             return;
2365         }
2366         if (thread->process != current->process)
2367         {
2368             release_object( thread );
2369             set_error( STATUS_ACCESS_DENIED );
2370             return;
2371         }
2372         queue = thread->queue;
2373         /* remove it if it existed already */
2374         if ((timer = find_timer( queue, win, req->msg, id ))) free_timer( queue, timer );
2375     }
2376     else
2377     {
2378         queue = get_current_queue();
2379         /* look for a timer with this id */
2380         if (id && (timer = find_timer( queue, 0, req->msg, id )))
2381         {
2382             /* free and reuse id */
2383             free_timer( queue, timer );
2384         }
2385         else
2386         {
2387             /* find a free id for it */
2388             do
2389             {
2390                 id = queue->next_timer_id;
2391                 if (--queue->next_timer_id <= 0x100) queue->next_timer_id = 0x7fff;
2392             }
2393             while (find_timer( queue, 0, req->msg, id ));
2394         }
2395     }
2396
2397     if ((timer = set_timer( queue, req->rate )))
2398     {
2399         timer->win    = win;
2400         timer->msg    = req->msg;
2401         timer->id     = id;
2402         timer->lparam = req->lparam;
2403         reply->id     = id;
2404     }
2405     if (thread) release_object( thread );
2406 }
2407
2408 /* kill a window timer */
2409 DECL_HANDLER(kill_win_timer)
2410 {
2411     struct timer *timer;
2412     struct thread *thread;
2413     user_handle_t win = 0;
2414
2415     if (req->win)
2416     {
2417         if (!(win = get_user_full_handle( req->win )) || !(thread = get_window_thread( win )))
2418         {
2419             set_error( STATUS_INVALID_HANDLE );
2420             return;
2421         }
2422         if (thread->process != current->process)
2423         {
2424             release_object( thread );
2425             set_error( STATUS_ACCESS_DENIED );
2426             return;
2427         }
2428     }
2429     else thread = (struct thread *)grab_object( current );
2430
2431     if (thread->queue && (timer = find_timer( thread->queue, win, req->msg, req->id )))
2432         free_timer( thread->queue, timer );
2433     else
2434         set_error( STATUS_INVALID_PARAMETER );
2435
2436     release_object( thread );
2437 }
2438
2439 DECL_HANDLER(register_hotkey)
2440 {
2441     struct desktop *desktop;
2442     user_handle_t win_handle = req->window;
2443     struct hotkey *hotkey;
2444     struct hotkey *new_hotkey = NULL;
2445     struct thread *thread;
2446     const int modifier_flags = MOD_ALT|MOD_CONTROL|MOD_SHIFT|MOD_WIN;
2447
2448     if (!(desktop = get_thread_desktop( current, 0 ))) return;
2449
2450     if (win_handle)
2451     {
2452         if (!get_user_object_handle( &win_handle, USER_WINDOW ))
2453         {
2454             release_object( desktop );
2455             set_win32_error( ERROR_INVALID_WINDOW_HANDLE );
2456             return;
2457         }
2458
2459         thread = get_window_thread( win_handle );
2460         if (thread) release_object( thread );
2461
2462         if (thread != current)
2463         {
2464             release_object( desktop );
2465             set_win32_error( ERROR_WINDOW_OF_OTHER_THREAD );
2466             return;
2467         }
2468     }
2469
2470     LIST_FOR_EACH_ENTRY( hotkey, &desktop->hotkeys, struct hotkey, entry )
2471     {
2472         if (req->vkey == hotkey->vkey &&
2473             (req->flags & modifier_flags) == (hotkey->flags & modifier_flags))
2474         {
2475             release_object( desktop );
2476             set_win32_error( ERROR_HOTKEY_ALREADY_REGISTERED );
2477             return;
2478         }
2479         if (current->queue == hotkey->queue && win_handle == hotkey->win && req->id == hotkey->id)
2480             new_hotkey = hotkey;
2481     }
2482
2483     if (new_hotkey)
2484     {
2485         reply->replaced = 1;
2486         reply->flags    = new_hotkey->flags;
2487         reply->vkey     = new_hotkey->vkey;
2488     }
2489     else
2490     {
2491         new_hotkey = mem_alloc( sizeof(*new_hotkey) );
2492         if (new_hotkey)
2493         {
2494             list_add_tail( &desktop->hotkeys, &new_hotkey->entry );
2495             new_hotkey->queue  = current->queue;
2496             new_hotkey->win    = win_handle;
2497             new_hotkey->id     = req->id;
2498         }
2499     }
2500
2501     if (new_hotkey)
2502     {
2503         new_hotkey->flags = req->flags;
2504         new_hotkey->vkey  = req->vkey;
2505     }
2506
2507     release_object( desktop );
2508 }
2509
2510 DECL_HANDLER(unregister_hotkey)
2511 {
2512     struct desktop *desktop;
2513     user_handle_t win_handle = req->window;
2514     struct hotkey *hotkey;
2515     struct thread *thread;
2516
2517     if (!(desktop = get_thread_desktop( current, 0 ))) return;
2518
2519     if (win_handle)
2520     {
2521         if (!get_user_object_handle( &win_handle, USER_WINDOW ))
2522         {
2523             release_object( desktop );
2524             set_win32_error( ERROR_INVALID_WINDOW_HANDLE );
2525             return;
2526         }
2527
2528         thread = get_window_thread( win_handle );
2529         if (thread) release_object( thread );
2530
2531         if (thread != current)
2532         {
2533             release_object( desktop );
2534             set_win32_error( ERROR_WINDOW_OF_OTHER_THREAD );
2535             return;
2536         }
2537     }
2538
2539     LIST_FOR_EACH_ENTRY( hotkey, &desktop->hotkeys, struct hotkey, entry )
2540     {
2541         if (current->queue == hotkey->queue && win_handle == hotkey->win && req->id == hotkey->id)
2542             goto found;
2543     }
2544
2545     release_object( desktop );
2546     set_win32_error( ERROR_HOTKEY_NOT_REGISTERED );
2547     return;
2548
2549 found:
2550     reply->flags = hotkey->flags;
2551     reply->vkey  = hotkey->vkey;
2552     list_remove( &hotkey->entry );
2553     free( hotkey );
2554     release_object( desktop );
2555 }
2556
2557 /* attach (or detach) thread inputs */
2558 DECL_HANDLER(attach_thread_input)
2559 {
2560     struct thread *thread_from = get_thread_from_id( req->tid_from );
2561     struct thread *thread_to = get_thread_from_id( req->tid_to );
2562
2563     if (!thread_from || !thread_to)
2564     {
2565         if (thread_from) release_object( thread_from );
2566         if (thread_to) release_object( thread_to );
2567         return;
2568     }
2569     if (thread_from != thread_to)
2570     {
2571         if (req->attach) attach_thread_input( thread_from, thread_to );
2572         else
2573         {
2574             if (thread_from->queue && thread_to->queue &&
2575                 thread_from->queue->input == thread_to->queue->input)
2576                 detach_thread_input( thread_from );
2577             else
2578                 set_error( STATUS_ACCESS_DENIED );
2579         }
2580     }
2581     else set_error( STATUS_ACCESS_DENIED );
2582     release_object( thread_from );
2583     release_object( thread_to );
2584 }
2585
2586
2587 /* get thread input data */
2588 DECL_HANDLER(get_thread_input)
2589 {
2590     struct thread *thread = NULL;
2591     struct desktop *desktop;
2592     struct thread_input *input;
2593
2594     if (req->tid)
2595     {
2596         if (!(thread = get_thread_from_id( req->tid ))) return;
2597         if (!(desktop = get_thread_desktop( thread, 0 )))
2598         {
2599             release_object( thread );
2600             return;
2601         }
2602         input = thread->queue ? thread->queue->input : NULL;
2603     }
2604     else
2605     {
2606         if (!(desktop = get_thread_desktop( current, 0 ))) return;
2607         input = desktop->foreground_input;  /* get the foreground thread info */
2608     }
2609
2610     if (input)
2611     {
2612         reply->focus      = input->focus;
2613         reply->capture    = input->capture;
2614         reply->active     = input->active;
2615         reply->menu_owner = input->menu_owner;
2616         reply->move_size  = input->move_size;
2617         reply->caret      = input->caret;
2618         reply->cursor     = input->cursor;
2619         reply->show_count = input->cursor_count;
2620         reply->rect       = input->caret_rect;
2621     }
2622
2623     /* foreground window is active window of foreground thread */
2624     reply->foreground = desktop->foreground_input ? desktop->foreground_input->active : 0;
2625     if (thread) release_object( thread );
2626     release_object( desktop );
2627 }
2628
2629
2630 /* retrieve queue keyboard state for a given thread */
2631 DECL_HANDLER(get_key_state)
2632 {
2633     struct thread *thread;
2634     struct desktop *desktop;
2635     data_size_t size = min( 256, get_reply_max_size() );
2636
2637     if (!req->tid)  /* get global async key state */
2638     {
2639         if (!(desktop = get_thread_desktop( current, 0 ))) return;
2640         if (req->key >= 0)
2641         {
2642             reply->state = desktop->keystate[req->key & 0xff];
2643             desktop->keystate[req->key & 0xff] &= ~0x40;
2644         }
2645         set_reply_data( desktop->keystate, size );
2646         release_object( desktop );
2647     }
2648     else
2649     {
2650         if (!(thread = get_thread_from_id( req->tid ))) return;
2651         if (thread->queue)
2652         {
2653             if (req->key >= 0) reply->state = thread->queue->input->keystate[req->key & 0xff];
2654             set_reply_data( thread->queue->input->keystate, size );
2655         }
2656         release_object( thread );
2657     }
2658 }
2659
2660
2661 /* set queue keyboard state for a given thread */
2662 DECL_HANDLER(set_key_state)
2663 {
2664     struct thread *thread;
2665     struct desktop *desktop;
2666     data_size_t size = min( 256, get_req_data_size() );
2667
2668     if (!req->tid)  /* set global async key state */
2669     {
2670         if (!(desktop = get_thread_desktop( current, 0 ))) return;
2671         memcpy( desktop->keystate, get_req_data(), size );
2672         release_object( desktop );
2673     }
2674     else
2675     {
2676         if (!(thread = get_thread_from_id( req->tid ))) return;
2677         if (thread->queue) memcpy( thread->queue->input->keystate, get_req_data(), size );
2678         release_object( thread );
2679     }
2680 }
2681
2682
2683 /* set the system foreground window */
2684 DECL_HANDLER(set_foreground_window)
2685 {
2686     struct thread *thread = NULL;
2687     struct desktop *desktop;
2688     struct msg_queue *queue = get_current_queue();
2689
2690     if (!(desktop = get_thread_desktop( current, 0 ))) return;
2691     reply->previous = desktop->foreground_input ? desktop->foreground_input->active : 0;
2692     reply->send_msg_old = (reply->previous && desktop->foreground_input != queue->input);
2693     reply->send_msg_new = FALSE;
2694
2695     if (is_top_level_window( req->handle ) &&
2696         ((thread = get_window_thread( req->handle ))) &&
2697         (thread->queue->input->desktop == desktop))
2698     {
2699         set_foreground_input( desktop, thread->queue->input );
2700         reply->send_msg_new = (desktop->foreground_input != queue->input);
2701     }
2702     else set_win32_error( ERROR_INVALID_WINDOW_HANDLE );
2703
2704     if (thread) release_object( thread );
2705     release_object( desktop );
2706 }
2707
2708
2709 /* set the current thread focus window */
2710 DECL_HANDLER(set_focus_window)
2711 {
2712     struct msg_queue *queue = get_current_queue();
2713
2714     reply->previous = 0;
2715     if (queue && check_queue_input_window( queue, req->handle ))
2716     {
2717         reply->previous = queue->input->focus;
2718         queue->input->focus = get_user_full_handle( req->handle );
2719     }
2720 }
2721
2722
2723 /* set the current thread active window */
2724 DECL_HANDLER(set_active_window)
2725 {
2726     struct msg_queue *queue = get_current_queue();
2727
2728     reply->previous = 0;
2729     if (queue && check_queue_input_window( queue, req->handle ))
2730     {
2731         if (!req->handle || make_window_active( req->handle ))
2732         {
2733             reply->previous = queue->input->active;
2734             queue->input->active = get_user_full_handle( req->handle );
2735         }
2736         else set_error( STATUS_INVALID_HANDLE );
2737     }
2738 }
2739
2740
2741 /* set the current thread capture window */
2742 DECL_HANDLER(set_capture_window)
2743 {
2744     struct msg_queue *queue = get_current_queue();
2745
2746     reply->previous = reply->full_handle = 0;
2747     if (queue && check_queue_input_window( queue, req->handle ))
2748     {
2749         struct thread_input *input = queue->input;
2750
2751         /* if in menu mode, reject all requests to change focus, except if the menu bit is set */
2752         if (input->menu_owner && !(req->flags & CAPTURE_MENU))
2753         {
2754             set_error(STATUS_ACCESS_DENIED);
2755             return;
2756         }
2757         reply->previous = input->capture;
2758         input->capture = get_user_full_handle( req->handle );
2759         input->menu_owner = (req->flags & CAPTURE_MENU) ? input->capture : 0;
2760         input->move_size = (req->flags & CAPTURE_MOVESIZE) ? input->capture : 0;
2761         reply->full_handle = input->capture;
2762     }
2763 }
2764
2765
2766 /* Set the current thread caret window */
2767 DECL_HANDLER(set_caret_window)
2768 {
2769     struct msg_queue *queue = get_current_queue();
2770
2771     reply->previous = 0;
2772     if (queue && check_queue_input_window( queue, req->handle ))
2773     {
2774         struct thread_input *input = queue->input;
2775
2776         reply->previous  = input->caret;
2777         reply->old_rect  = input->caret_rect;
2778         reply->old_hide  = input->caret_hide;
2779         reply->old_state = input->caret_state;
2780
2781         set_caret_window( input, get_user_full_handle(req->handle) );
2782         input->caret_rect.right  = input->caret_rect.left + req->width;
2783         input->caret_rect.bottom = input->caret_rect.top + req->height;
2784     }
2785 }
2786
2787
2788 /* Set the current thread caret information */
2789 DECL_HANDLER(set_caret_info)
2790 {
2791     struct msg_queue *queue = get_current_queue();
2792     struct thread_input *input;
2793
2794     if (!queue) return;
2795     input = queue->input;
2796     reply->full_handle = input->caret;
2797     reply->old_rect    = input->caret_rect;
2798     reply->old_hide    = input->caret_hide;
2799     reply->old_state   = input->caret_state;
2800
2801     if (req->handle && get_user_full_handle(req->handle) != input->caret)
2802     {
2803         set_error( STATUS_ACCESS_DENIED );
2804         return;
2805     }
2806     if (req->flags & SET_CARET_POS)
2807     {
2808         input->caret_rect.right  += req->x - input->caret_rect.left;
2809         input->caret_rect.bottom += req->y - input->caret_rect.top;
2810         input->caret_rect.left = req->x;
2811         input->caret_rect.top  = req->y;
2812     }
2813     if (req->flags & SET_CARET_HIDE)
2814     {
2815         input->caret_hide += req->hide;
2816         if (input->caret_hide < 0) input->caret_hide = 0;
2817     }
2818     if (req->flags & SET_CARET_STATE)
2819     {
2820         if (req->state == -1) input->caret_state = !input->caret_state;
2821         else input->caret_state = !!req->state;
2822     }
2823 }
2824
2825
2826 /* get the time of the last input event */
2827 DECL_HANDLER(get_last_input_time)
2828 {
2829     reply->time = last_input_time;
2830 }
2831
2832 /* set/get the current cursor */
2833 DECL_HANDLER(set_cursor)
2834 {
2835     struct msg_queue *queue = get_current_queue();
2836     struct thread_input *input;
2837
2838     if (!queue) return;
2839     input = queue->input;
2840
2841     reply->prev_handle = input->cursor;
2842     reply->prev_count  = input->cursor_count;
2843     reply->prev_x      = input->desktop->cursor.x;
2844     reply->prev_y      = input->desktop->cursor.y;
2845
2846     if (req->flags & SET_CURSOR_HANDLE)
2847     {
2848         if (req->handle && !get_user_object( req->handle, USER_CLIENT ))
2849         {
2850             set_win32_error( ERROR_INVALID_CURSOR_HANDLE );
2851             return;
2852         }
2853         input->cursor = req->handle;
2854     }
2855     if (req->flags & SET_CURSOR_COUNT)
2856     {
2857         queue->cursor_count += req->show_count;
2858         input->cursor_count += req->show_count;
2859     }
2860     if (req->flags & SET_CURSOR_POS)
2861     {
2862         set_cursor_pos( input->desktop, req->x, req->y );
2863     }
2864     if (req->flags & SET_CURSOR_CLIP)
2865     {
2866         struct desktop *desktop = input->desktop;
2867
2868         /* only the desktop owner can set the message */
2869         if (req->clip_msg && get_top_window_owner(desktop) == current->process)
2870             desktop->cursor.clip_msg = req->clip_msg;
2871
2872         set_clip_rectangle( desktop, &req->clip );
2873     }
2874
2875     reply->new_x       = input->desktop->cursor.x;
2876     reply->new_y       = input->desktop->cursor.y;
2877     reply->new_clip    = input->desktop->cursor.clip;
2878     reply->last_change = input->desktop->cursor.last_change;
2879 }