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