Skip queue cleanups if queue has been destroyed already.
[wine] / server / queue.c
1 /*
2  * Server-side message queues
3  *
4  * Copyright (C) 2000 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10
11 #include "winbase.h"
12 #include "wingdi.h"
13 #include "winuser.h"
14
15 #include "handle.h"
16 #include "thread.h"
17 #include "process.h"
18 #include "request.h"
19 #include "user.h"
20
21 enum message_kind { SEND_MESSAGE, POST_MESSAGE, COOKED_HW_MESSAGE, RAW_HW_MESSAGE };
22 #define NB_MSG_KINDS (RAW_HW_MESSAGE+1)
23
24
25 struct message_result
26 {
27     struct message_result *send_next;   /* next in sender list */
28     struct message_result *recv_next;   /* next in receiver list */
29     struct msg_queue      *sender;      /* sender queue */
30     struct msg_queue      *receiver;    /* receiver queue */
31     int                    replied;     /* has it been replied to? */
32     unsigned int           result;      /* reply result */
33     unsigned int           error;       /* error code to pass back to sender */
34     void                  *data;        /* message reply data */
35     unsigned int           data_size;   /* size of message reply data */
36     struct timeout_user   *timeout;     /* result timeout */
37 };
38
39 struct message
40 {
41     struct message        *next;      /* next message in list */
42     struct message        *prev;      /* prev message in list */
43     enum message_type      type;      /* message type */
44     user_handle_t          win;       /* window handle */
45     unsigned int           msg;       /* message code */
46     unsigned int           wparam;    /* parameters */
47     unsigned int           lparam;    /* parameters */
48     int                    x;         /* x position */
49     int                    y;         /* y position */
50     unsigned int           time;      /* message time */
51     unsigned int           info;      /* extra info */
52     void                  *data;      /* message data for sent messages */
53     unsigned int           data_size; /* size of message data */
54     struct message_result *result;    /* result in sender queue */
55 };
56
57 struct message_list
58 {
59     struct message *first;     /* head of list */
60     struct message *last;      /* tail of list */
61 };
62
63 struct timer
64 {
65     struct timer   *next;      /* next timer in list */
66     struct timer   *prev;      /* prev timer in list */
67     struct timeval  when;      /* next expiration */
68     unsigned int    rate;      /* timer rate in ms */
69     user_handle_t   win;       /* window handle */
70     unsigned int    msg;       /* message to post */
71     unsigned int    id;        /* timer id */
72     unsigned int    lparam;    /* lparam for message */
73 };
74
75 struct msg_queue
76 {
77     struct object          obj;           /* object header */
78     unsigned int           wake_bits;     /* wakeup bits */
79     unsigned int           wake_mask;     /* wakeup mask */
80     unsigned int           changed_bits;  /* changed wakeup bits */
81     unsigned int           changed_mask;  /* changed wakeup mask */
82     int                    paint_count;   /* pending paint messages count */
83     struct message_list    msg_list[NB_MSG_KINDS];  /* lists of messages */
84     struct message_result *send_result;   /* stack of sent messages waiting for result */
85     struct message_result *recv_result;   /* stack of received messages waiting for result */
86     struct message        *last_msg;      /* last msg returned to the app and not removed */
87     enum message_kind      last_msg_kind; /* message kind of last_msg */
88     struct timer          *first_timer;   /* head of timer list */
89     struct timer          *last_timer;    /* tail of timer list */
90     struct timer          *next_timer;    /* next timer to expire */
91     struct timeout_user   *timeout;       /* timeout for next timer to expire */
92 };
93
94 static void msg_queue_dump( struct object *obj, int verbose );
95 static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry );
96 static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry );
97 static int msg_queue_signaled( struct object *obj, struct thread *thread );
98 static int msg_queue_satisfied( struct object *obj, struct thread *thread );
99 static void msg_queue_destroy( struct object *obj );
100 static void timer_callback( void *private );
101
102 static const struct object_ops msg_queue_ops =
103 {
104     sizeof(struct msg_queue),  /* size */
105     msg_queue_dump,            /* dump */
106     msg_queue_add_queue,       /* add_queue */
107     msg_queue_remove_queue,    /* remove_queue */
108     msg_queue_signaled,        /* signaled */
109     msg_queue_satisfied,       /* satisfied */
110     NULL,                      /* get_poll_events */
111     NULL,                      /* poll_event */
112     no_get_fd,                 /* get_fd */
113     no_flush,                  /* flush */
114     no_get_file_info,          /* get_file_info */
115     msg_queue_destroy          /* destroy */
116 };
117
118
119 static struct msg_queue *create_msg_queue( struct thread *thread )
120 {
121     struct msg_queue *queue;
122     int i;
123
124     if ((queue = alloc_object( &msg_queue_ops, -1 )))
125     {
126         queue->wake_bits       = 0;
127         queue->wake_mask       = 0;
128         queue->changed_bits    = 0;
129         queue->changed_mask    = 0;
130         queue->paint_count     = 0;
131         queue->send_result     = NULL;
132         queue->recv_result     = NULL;
133         queue->last_msg        = NULL;
134         queue->first_timer     = NULL;
135         queue->last_timer      = NULL;
136         queue->next_timer      = NULL;
137         queue->timeout         = NULL;
138         for (i = 0; i < NB_MSG_KINDS; i++)
139             queue->msg_list[i].first = queue->msg_list[i].last = NULL;
140
141         thread->queue = queue;
142         if (!thread->process->queue)
143             thread->process->queue = (struct msg_queue *)grab_object( queue );
144     }
145     return queue;
146 }
147
148 /* check the queue status */
149 inline static int is_signaled( struct msg_queue *queue )
150 {
151     return ((queue->wake_bits & queue->wake_mask) || (queue->changed_bits & queue->changed_mask));
152 }
153
154 /* set some queue bits */
155 inline static void set_queue_bits( struct msg_queue *queue, unsigned int bits )
156 {
157     queue->wake_bits |= bits;
158     queue->changed_bits |= bits;
159     if (is_signaled( queue )) wake_up( &queue->obj, 0 );
160 }
161
162 /* clear some queue bits */
163 inline static void clear_queue_bits( struct msg_queue *queue, unsigned int bits )
164 {
165     queue->wake_bits &= ~bits;
166     queue->changed_bits &= ~bits;
167 }
168
169 /* get the QS_* bit corresponding to a given hardware message */
170 inline static int get_hardware_msg_bit( struct message *msg )
171 {
172     if (msg->msg == WM_MOUSEMOVE || msg->msg == WM_NCMOUSEMOVE) return QS_MOUSEMOVE;
173     if (msg->msg >= WM_KEYFIRST && msg->msg <= WM_KEYLAST) return QS_KEY;
174     return QS_MOUSEBUTTON;
175 }
176
177 /* get the current thread queue, creating it if needed */
178 inline static struct msg_queue *get_current_queue(void)
179 {
180     struct msg_queue *queue = current->queue;
181     if (!queue) queue = create_msg_queue( current );
182     return queue;
183 }
184
185 /* append a message to the end of a list */
186 inline static void append_message( struct message_list *list, struct message *msg )
187 {
188     msg->next = NULL;
189     if ((msg->prev = list->last)) msg->prev->next = msg;
190     else list->first = msg;
191     list->last = msg;
192 }
193
194 /* unlink a message from a list it */
195 inline static void unlink_message( struct message_list *list, struct message *msg )
196 {
197     if (msg->next) msg->next->prev = msg->prev;
198     else list->last = msg->prev;
199     if (msg->prev) msg->prev->next = msg->next;
200     else list->first = msg->next;
201 }
202
203 /* try to merge a message with the last in the list; return 1 if successful */
204 static int merge_message( struct message_list *list, const struct message *msg )
205 {
206     struct message *prev = list->last;
207
208     if (!prev) return 0;
209     if (prev->result) return 0;
210     if (prev->win != msg->win) return 0;
211     if (prev->msg != msg->msg) return 0;
212     if (prev->type != msg->type) return 0;
213     /* now we can merge it */
214     prev->wparam  = msg->wparam;
215     prev->lparam  = msg->lparam;
216     prev->x       = msg->x;
217     prev->y       = msg->y;
218     prev->time    = msg->time;
219     prev->info    = msg->info;
220     return 1;
221 }
222
223 /* free a result structure */
224 static void free_result( struct message_result *result )
225 {
226     if (result->timeout) remove_timeout_user( result->timeout );
227     if (result->data) free( result->data );
228     free( result );
229 }
230
231 /* store the message result in the appropriate structure */
232 static void store_message_result( struct message_result *res, unsigned int result,
233                                   unsigned int error )
234 {
235     res->result  = result;
236     res->error   = error;
237     res->replied = 1;
238     if (res->timeout)
239     {
240         remove_timeout_user( res->timeout );
241         res->timeout = NULL;
242     }
243     /* wake sender queue if waiting on this result */
244     if (res->sender && res->sender->send_result == res)
245         set_queue_bits( res->sender, QS_SMRESULT );
246 }
247
248 /* free a message when deleting a queue or window */
249 static void free_message( struct message *msg )
250 {
251     struct message_result *result = msg->result;
252     if (result)
253     {
254         if (result->sender)
255         {
256             result->receiver = NULL;
257             store_message_result( result, 0, STATUS_ACCESS_DENIED /*FIXME*/ );
258         }
259         else free_result( result );
260     }
261     if (msg->data) free( msg->data );
262     free( msg );
263 }
264
265 /* remove (and free) a message from a message list */
266 static void remove_queue_message( struct msg_queue *queue, struct message *msg,
267                                   enum message_kind kind )
268 {
269     int clr_bit;
270     struct message *other;
271
272     if (queue->last_msg == msg) queue->last_msg = NULL;
273     unlink_message( &queue->msg_list[kind], msg );
274     switch(kind)
275     {
276     case SEND_MESSAGE:
277         if (!queue->msg_list[kind].first) clear_queue_bits( queue, QS_SENDMESSAGE );
278         break;
279     case POST_MESSAGE:
280         if (!queue->msg_list[kind].first) clear_queue_bits( queue, QS_POSTMESSAGE );
281         break;
282     case COOKED_HW_MESSAGE:
283     case RAW_HW_MESSAGE:
284         clr_bit = get_hardware_msg_bit( msg );
285         for (other = queue->msg_list[kind].first; other; other = other->next)
286             if (get_hardware_msg_bit( other ) == clr_bit) break;
287         if (!other) clear_queue_bits( queue, clr_bit );
288         break;
289     }
290     free_message( msg );
291 }
292
293 /* message timed out without getting a reply */
294 static void result_timeout( void *private )
295 {
296     struct message_result *result = private;
297
298     assert( !result->replied );
299
300     result->timeout = NULL;
301     store_message_result( result, 0, STATUS_TIMEOUT );
302 }
303
304 /* allocate and fill a message result structure */
305 static struct message_result *alloc_message_result( struct msg_queue *send_queue,
306                                                     struct msg_queue *recv_queue,
307                                                     unsigned int timeout )
308 {
309     struct message_result *result = mem_alloc( sizeof(*result) );
310     if (result)
311     {
312         /* put the result on the sender result stack */
313         result->sender    = send_queue;
314         result->receiver  = recv_queue;
315         result->replied   = 0;
316         result->data      = NULL;
317         result->data_size = 0;
318         result->timeout   = NULL;
319         result->send_next = send_queue->send_result;
320         send_queue->send_result = result;
321         if (timeout != -1)
322         {
323             struct timeval when;
324             gettimeofday( &when, 0 );
325             add_timeout( &when, timeout );
326             result->timeout = add_timeout_user( &when, result_timeout, result );
327         }
328     }
329     return result;
330 }
331
332 /* receive a message, removing it from the sent queue */
333 static void receive_message( struct msg_queue *queue, struct message *msg )
334 {
335     struct message_result *result = msg->result;
336
337     unlink_message( &queue->msg_list[SEND_MESSAGE], msg );
338     /* put the result on the receiver result stack */
339     if (result)
340     {
341         result->recv_next  = queue->recv_result;
342         queue->recv_result = result;
343     }
344     if (msg->data) free( msg->data );
345     free( msg );
346     if (!queue->msg_list[SEND_MESSAGE].first) clear_queue_bits( queue, QS_SENDMESSAGE );
347 }
348
349 /* set the result of the current received message */
350 static void reply_message( struct msg_queue *queue, unsigned int result,
351                            unsigned int error, int remove, void *data, size_t len )
352 {
353     struct message_result *res = queue->recv_result;
354
355     if (remove)
356     {
357         queue->recv_result = res->recv_next;
358         res->receiver = NULL;
359         if (!res->sender)  /* no one waiting for it */
360         {
361             free_result( res );
362             return;
363         }
364     }
365     if (!res->replied)
366     {
367         if (len && (res->data = memdup( data, len ))) res->data_size = len;
368         store_message_result( res, result, error );
369     }
370 }
371
372 /* empty a message list and free all the messages */
373 static void empty_msg_list( struct message_list *list )
374 {
375     struct message *msg = list->first;
376     while (msg)
377     {
378         struct message *next = msg->next;
379         free_message( msg );
380         msg = next;
381     }
382 }
383
384 /* cleanup all pending results when deleting a queue */
385 static void cleanup_results( struct msg_queue *queue )
386 {
387     struct message_result *result, *next;
388
389     result = queue->send_result;
390     while (result)
391     {
392         next = result->send_next;
393         result->sender = NULL;
394         if (!result->receiver) free_result( result );
395         result = next;
396     }
397
398     while (queue->recv_result)
399         reply_message( queue, 0, STATUS_ACCESS_DENIED /*FIXME*/, 1, NULL, 0 );
400 }
401
402 static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry )
403 {
404     struct msg_queue *queue = (struct msg_queue *)obj;
405     struct process *process = entry->thread->process;
406
407     /* a thread can only wait on its own queue */
408     if (entry->thread->queue != queue)
409     {
410         set_error( STATUS_ACCESS_DENIED );
411         return 0;
412     }
413     /* if waiting on the main process queue, set the idle event */
414     if (process->queue == queue)
415     {
416         if (process->idle_event) set_event( process->idle_event );
417     }
418     add_queue( obj, entry );
419     return 1;
420 }
421
422 static void msg_queue_remove_queue(struct object *obj, struct wait_queue_entry *entry )
423 {
424     struct msg_queue *queue = (struct msg_queue *)obj;
425     struct process *process = entry->thread->process;
426
427     remove_queue( obj, entry );
428
429     assert( entry->thread->queue == queue );
430
431     /* if waiting on the main process queue, reset the idle event */
432     if (process->queue == queue)
433     {
434         if (process->idle_event) reset_event( process->idle_event );
435     }
436 }
437
438 static void msg_queue_dump( struct object *obj, int verbose )
439 {
440     struct msg_queue *queue = (struct msg_queue *)obj;
441     fprintf( stderr, "Msg queue bits=%x mask=%x\n",
442              queue->wake_bits, queue->wake_mask );
443 }
444
445 static int msg_queue_signaled( struct object *obj, struct thread *thread )
446 {
447     struct msg_queue *queue = (struct msg_queue *)obj;
448     return is_signaled( queue );
449 }
450
451 static int msg_queue_satisfied( struct object *obj, struct thread *thread )
452 {
453     struct msg_queue *queue = (struct msg_queue *)obj;
454     queue->wake_mask = 0;
455     queue->changed_mask = 0;
456     return 0;  /* Not abandoned */
457 }
458
459 static void msg_queue_destroy( struct object *obj )
460 {
461     struct msg_queue *queue = (struct msg_queue *)obj;
462     struct timer *timer = queue->first_timer;
463     int i;
464
465     cleanup_results( queue );
466     for (i = 0; i < NB_MSG_KINDS; i++) empty_msg_list( &queue->msg_list[i] );
467
468     while (timer)
469     {
470         struct timer *next = timer->next;
471         free( timer );
472         timer = next;
473     }
474     if (queue->timeout) remove_timeout_user( queue->timeout );
475 }
476
477 /* set the next timer to expire */
478 static void set_next_timer( struct msg_queue *queue, struct timer *timer )
479 {
480     if (queue->timeout)
481     {
482         remove_timeout_user( queue->timeout );
483         queue->timeout = NULL;
484     }
485     if ((queue->next_timer = timer))
486         queue->timeout = add_timeout_user( &timer->when, timer_callback, queue );
487
488     /* set/clear QS_TIMER bit */
489     if (queue->next_timer == queue->first_timer)
490         clear_queue_bits( queue, QS_TIMER );
491     else
492         set_queue_bits( queue, QS_TIMER );
493 }
494
495 /* callback for the next timer expiration */
496 static void timer_callback( void *private )
497 {
498     struct msg_queue *queue = private;
499
500     queue->timeout = NULL;
501     /* move on to the next timer */
502     set_next_timer( queue, queue->next_timer->next );
503 }
504
505 /* link a timer at its rightful place in the queue list */
506 static void link_timer( struct msg_queue *queue, struct timer *timer )
507 {
508     struct timer *pos = queue->next_timer;
509
510     while (pos && time_before( &pos->when, &timer->when )) pos = pos->next;
511
512     if (pos) /* insert before pos */
513     {
514         if ((timer->prev = pos->prev)) timer->prev->next = timer;
515         else queue->first_timer = timer;
516         timer->next = pos;
517         pos->prev = timer;
518     }
519     else  /* insert at end */
520     {
521         timer->next = NULL;
522         timer->prev = queue->last_timer;
523         if (queue->last_timer) queue->last_timer->next = timer;
524         else queue->first_timer = timer;
525         queue->last_timer = timer;
526     }
527     /* check if we replaced the next timer */
528     if (pos == queue->next_timer) set_next_timer( queue, timer );
529 }
530
531 /* remove a timer from the queue timer list */
532 static void unlink_timer( struct msg_queue *queue, struct timer *timer )
533 {
534     if (timer->next) timer->next->prev = timer->prev;
535     else queue->last_timer = timer->prev;
536     if (timer->prev) timer->prev->next = timer->next;
537     else queue->first_timer = timer->next;
538     /* check if we removed the next timer */
539     if (queue->next_timer == timer) set_next_timer( queue, timer->next );
540     else if (queue->next_timer == queue->first_timer) clear_queue_bits( queue, QS_TIMER );
541 }
542
543 /* restart an expired timer */
544 static void restart_timer( struct msg_queue *queue, struct timer *timer )
545 {
546     struct timeval now;
547     unlink_timer( queue, timer );
548     gettimeofday( &now, 0 );
549     while (!time_before( &now, &timer->when )) add_timeout( &timer->when, timer->rate );
550     link_timer( queue, timer );
551 }
552
553 /* find an expired timer matching the filtering parameters */
554 static struct timer *find_expired_timer( struct msg_queue *queue, user_handle_t win,
555                                          unsigned int get_first, unsigned int get_last,
556                                          int remove )
557 {
558     struct timer *timer;
559     for (timer = queue->first_timer; (timer && timer != queue->next_timer); timer = timer->next)
560     {
561         if (win && timer->win != win) continue;
562         if (timer->msg >= get_first && timer->msg <= get_last)
563         {
564             if (remove) restart_timer( queue, timer );
565             return timer;
566         }
567     }
568     return NULL;
569 }
570
571 /* kill a timer */
572 static int kill_timer( struct msg_queue *queue, user_handle_t win,
573                        unsigned int msg, unsigned int id )
574 {
575     struct timer *timer;
576
577     for (timer = queue->first_timer; timer; timer = timer->next)
578     {
579         if (timer->win != win || timer->msg != msg || timer->id != id) continue;
580         unlink_timer( queue, timer );
581         free( timer );
582         return 1;
583     }
584     return 0;
585 }
586
587 /* add a timer */
588 static struct timer *set_timer( struct msg_queue *queue, unsigned int rate )
589 {
590     struct timer *timer = mem_alloc( sizeof(*timer) );
591     if (timer)
592     {
593         timer->rate  = rate;
594         gettimeofday( &timer->when, 0 );
595         add_timeout( &timer->when, rate );
596         link_timer( queue, timer );
597     }
598     return timer;
599 }
600
601
602 /* increment (or decrement if 'incr' is negative) the queue paint count */
603 void inc_queue_paint_count( struct thread *thread, int incr )
604 {
605     struct msg_queue *queue = thread->queue;
606
607     assert( queue );
608
609     if ((queue->paint_count += incr) < 0) queue->paint_count = 0;
610
611     if (queue->paint_count)
612         set_queue_bits( queue, QS_PAINT );
613     else
614         clear_queue_bits( queue, QS_PAINT );
615 }
616
617
618 /* remove all messages and timers belonging to a certain window */
619 void queue_cleanup_window( struct thread *thread, user_handle_t win )
620 {
621     struct msg_queue *queue = thread->queue;
622     struct timer *timer;
623     struct message *msg;
624     int i;
625
626     if (!queue) return;
627
628     /* remove timers */
629     timer = queue->first_timer;
630     while (timer)
631     {
632         struct timer *next = timer->next;
633         if (timer->win == win)
634         {
635             unlink_timer( queue, timer );
636             free( timer );
637         }
638         timer = next;
639     }
640
641     /* remove messages */
642     for (i = 0; i < NB_MSG_KINDS; i++)
643     {
644         msg = queue->msg_list[i].first;
645         while (msg)
646         {
647             struct message *next = msg->next;
648             if (msg->win == win) remove_queue_message( queue, msg, i );
649             msg = next;
650         }
651     }
652 }
653
654 /* get the message queue of the current thread */
655 DECL_HANDLER(get_msg_queue)
656 {
657     struct msg_queue *queue = get_current_queue();
658
659     req->handle = 0;
660     if (queue) req->handle = alloc_handle( current->process, queue, SYNCHRONIZE, 0 );
661 }
662
663
664 /* set the current message queue wakeup mask */
665 DECL_HANDLER(set_queue_mask)
666 {
667     struct msg_queue *queue = get_current_queue();
668
669     if (queue)
670     {
671         queue->wake_mask    = req->wake_mask;
672         queue->changed_mask = req->changed_mask;
673         req->wake_bits      = queue->wake_bits;
674         req->changed_bits   = queue->changed_bits;
675         if (is_signaled( queue ))
676         {
677             /* if skip wait is set, do what would have been done in the subsequent wait */
678             if (req->skip_wait) msg_queue_satisfied( &queue->obj, current );
679             else wake_up( &queue->obj, 0 );
680         }
681     }
682 }
683
684
685 /* get the current message queue status */
686 DECL_HANDLER(get_queue_status)
687 {
688     struct msg_queue *queue = current->queue;
689     if (queue)
690     {
691         req->wake_bits    = queue->wake_bits;
692         req->changed_bits = queue->changed_bits;
693         if (req->clear) queue->changed_bits = 0;
694     }
695     else req->wake_bits = req->changed_bits = 0;
696 }
697
698
699 /* send a message to a thread queue */
700 DECL_HANDLER(send_message)
701 {
702     struct message *msg;
703     struct msg_queue *send_queue = get_current_queue();
704     struct msg_queue *recv_queue;
705     struct thread *thread = get_thread_from_id( req->id );
706
707     if (!thread) return;
708
709     if (!(recv_queue = thread->queue))
710     {
711         set_error( STATUS_INVALID_PARAMETER );
712         release_object( thread );
713         return;
714     }
715
716     if ((msg = mem_alloc( sizeof(*msg) )))
717     {
718         msg->type      = req->type;
719         msg->win       = get_user_full_handle( req->win );
720         msg->msg       = req->msg;
721         msg->wparam    = req->wparam;
722         msg->lparam    = req->lparam;
723         msg->time      = req->time;
724         msg->x         = req->x;
725         msg->y         = req->y;
726         msg->info      = req->info;
727         msg->result    = NULL;
728         msg->data      = NULL;
729         msg->data_size = 0;
730
731         switch(msg->type)
732         {
733        case MSG_OTHER_PROCESS:
734             msg->data_size = get_req_data_size(req);
735             if (msg->data_size && !(msg->data = memdup( get_req_data(req), msg->data_size )))
736             {
737                 free( msg );
738                 break;
739             }
740             /* fall through */
741         case MSG_ASCII:
742         case MSG_UNICODE:
743         case MSG_CALLBACK:
744             if (!(msg->result = alloc_message_result( send_queue, recv_queue, req->timeout )))
745             {
746                 free( msg );
747                 break;
748             }
749             /* fall through */
750         case MSG_NOTIFY:
751             append_message( &recv_queue->msg_list[SEND_MESSAGE], msg );
752             set_queue_bits( recv_queue, QS_SENDMESSAGE );
753             break;
754         case MSG_POSTED:
755             append_message( &recv_queue->msg_list[POST_MESSAGE], msg );
756             set_queue_bits( recv_queue, QS_POSTMESSAGE );
757             break;
758         case MSG_HARDWARE_RAW:
759         case MSG_HARDWARE_COOKED:
760             {
761                 struct message_list *list = ((msg->type == MSG_HARDWARE_RAW) ?
762                                              &recv_queue->msg_list[RAW_HW_MESSAGE] :
763                                              &recv_queue->msg_list[COOKED_HW_MESSAGE]);
764                 if (msg->msg == WM_MOUSEMOVE && merge_message( list, msg ))
765                 {
766                     free( msg );
767                     break;
768                 }
769                 append_message( list, msg );
770                 set_queue_bits( recv_queue, get_hardware_msg_bit(msg) );
771                 break;
772             }
773         default:
774             set_error( STATUS_INVALID_PARAMETER );
775             free( msg );
776             break;
777         }
778     }
779     release_object( thread );
780 }
781
782 /* store a message contents into the request buffer; helper for get_message */
783 inline static void put_req_message( struct get_message_request *req, const struct message *msg )
784 {
785     int len = min( get_req_data_size(req), msg->data_size );
786
787     req->type   = msg->type;
788     req->win    = msg->win;
789     req->msg    = msg->msg;
790     req->wparam = msg->wparam;
791     req->lparam = msg->lparam;
792     req->x      = msg->x;
793     req->y      = msg->y;
794     req->time   = msg->time;
795     req->info   = msg->info;
796     if (len) memcpy( get_req_data(req), msg->data, len );
797     set_req_data_size( req, len );
798 }
799
800 /* return a message to the application, removing it from the queue if needed */
801 static void return_message_to_app( struct msg_queue *queue, struct get_message_request *req,
802                                    struct message *msg, enum message_kind kind )
803 {
804     put_req_message( req, msg );
805     /* raw messages always get removed */
806     if ((msg->type == MSG_HARDWARE_RAW) || (req->flags & GET_MSG_REMOVE))
807     {
808         queue->last_msg = NULL;
809         remove_queue_message( queue, msg, kind );
810     }
811     else  /* remember it as the last returned message */
812     {
813         queue->last_msg = msg;
814         queue->last_msg_kind = kind;
815     }
816 }
817
818
819 inline static struct message *find_matching_message( const struct message_list *list,
820                                                      user_handle_t win,
821                                                      unsigned int first, unsigned int last )
822 {
823     struct message *msg;
824
825     for (msg = list->first; msg; msg = msg->next)
826     {
827         /* check against the filters */
828         if (msg->msg == WM_QUIT) break;  /* WM_QUIT is never filtered */
829         if (win && msg->win && msg->win != win && !is_child_window( win, msg->win )) continue;
830         if (msg->msg < first) continue;
831         if (msg->msg > last) continue;
832         break; /* found one */
833     }
834     return msg;
835 }
836
837
838 /* get a message from the current queue */
839 DECL_HANDLER(get_message)
840 {
841     struct timer *timer;
842     struct message *msg;
843     struct msg_queue *queue = get_current_queue();
844     user_handle_t get_win = get_user_full_handle( req->get_win );
845
846     if (!queue)
847     {
848         set_req_data_size( req, 0 );
849         return;
850     }
851
852     /* first check for sent messages */
853     if ((msg = queue->msg_list[SEND_MESSAGE].first))
854     {
855         put_req_message( req, msg );
856         receive_message( queue, msg );
857         return;
858     }
859     set_req_data_size( req, 0 ); /* only sent messages can have data */
860     if (req->flags & GET_MSG_SENT_ONLY) goto done;  /* nothing else to check */
861
862     /* if requested, remove the last returned but not yet removed message */
863     if ((req->flags & GET_MSG_REMOVE_LAST) && queue->last_msg)
864         remove_queue_message( queue, queue->last_msg, queue->last_msg_kind );
865     queue->last_msg = NULL;
866
867     /* clear changed bits so we can wait on them if we don't find a message */
868     queue->changed_bits = 0;
869
870     /* then check for posted messages */
871     if ((msg = find_matching_message( &queue->msg_list[POST_MESSAGE], get_win,
872                                       req->get_first, req->get_last )))
873     {
874         return_message_to_app( queue, req, msg, POST_MESSAGE );
875         return;
876     }
877
878     /* then check for cooked hardware messages */
879     if ((msg = find_matching_message( &queue->msg_list[COOKED_HW_MESSAGE], get_win,
880                                       req->get_first, req->get_last )))
881     {
882         return_message_to_app( queue, req, msg, COOKED_HW_MESSAGE );
883         return;
884     }
885
886     /* then check for any raw hardware message */
887     if ((msg = queue->msg_list[RAW_HW_MESSAGE].first))
888     {
889         return_message_to_app( queue, req, msg, RAW_HW_MESSAGE );
890         return;
891     }
892
893     /* now check for WM_PAINT */
894     if (queue->paint_count &&
895         (WM_PAINT >= req->get_first) && (WM_PAINT <= req->get_last) &&
896         (req->win = find_window_to_repaint( get_win, current )))
897     {
898         req->type   = MSG_POSTED;
899         req->msg    = WM_PAINT;
900         req->wparam = 0;
901         req->lparam = 0;
902         req->x      = 0;
903         req->y      = 0;
904         req->time   = get_tick_count();
905         req->info   = 0;
906         return;
907     }
908
909     /* now check for timer */
910     if ((timer = find_expired_timer( queue, get_win, req->get_first,
911                                      req->get_last, (req->flags & GET_MSG_REMOVE) )))
912     {
913         req->type   = MSG_POSTED;
914         req->win    = timer->win;
915         req->msg    = timer->msg;
916         req->wparam = timer->id;
917         req->lparam = timer->lparam;
918         req->x      = 0;
919         req->y      = 0;
920         req->time   = get_tick_count();
921         req->info   = 0;
922         return;
923     }
924
925  done:
926     set_error( STATUS_PENDING );  /* FIXME */
927 }
928
929
930 /* reply to a sent message */
931 DECL_HANDLER(reply_message)
932 {
933     if (current->queue && current->queue->recv_result)
934         reply_message( current->queue, req->result, 0, req->remove,
935                        get_req_data(req), get_req_data_size(req) );
936     else
937         set_error( STATUS_ACCESS_DENIED );
938 }
939
940
941 /* retrieve the reply for the last message sent */
942 DECL_HANDLER(get_message_reply)
943 {
944     struct msg_queue *queue = current->queue;
945     size_t data_len = 0;
946
947     if (queue)
948     {
949         struct message_result *result = queue->send_result;
950
951         set_error( STATUS_PENDING );
952         req->result = 0;
953
954         if (result && (result->replied || req->cancel))
955         {
956             if (result->replied)
957             {
958                 req->result = result->result;
959                 set_error( result->error );
960                 if (result->data)
961                 {
962                     data_len = min( result->data_size, get_req_data_size(req) );
963                     memcpy( get_req_data(req), result->data, data_len );
964                     free( result->data );
965                     result->data = NULL;
966                     result->data_size = 0;
967                 }
968             }
969             queue->send_result = result->send_next;
970             result->sender = NULL;
971             if (!result->receiver) free_result( result );
972             if (!queue->send_result || !queue->send_result->replied)
973                 clear_queue_bits( queue, QS_SMRESULT );
974         }
975     }
976     else set_error( STATUS_ACCESS_DENIED );
977     set_req_data_size( req, data_len );
978 }
979
980
981 /* set a window timer */
982 DECL_HANDLER(set_win_timer)
983 {
984     struct timer *timer;
985     struct msg_queue *queue = get_current_queue();
986     user_handle_t win = get_user_full_handle( req->win );
987
988     if (!queue) return;
989
990     /* remove it if it existed already */
991     if (win) kill_timer( queue, win, req->msg, req->id );
992
993     if ((timer = set_timer( queue, req->rate )))
994     {
995         timer->win    = win;
996         timer->msg    = req->msg;
997         timer->id     = req->id;
998         timer->lparam = req->lparam;
999     }
1000 }
1001
1002 /* kill a window timer */
1003 DECL_HANDLER(kill_win_timer)
1004 {
1005     struct msg_queue *queue = current->queue;
1006
1007     if (!queue || !kill_timer( queue, get_user_full_handle(req->win), req->msg, req->id ))
1008         set_error( STATUS_INVALID_PARAMETER );
1009 }