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