Implement SHRegGetBoolUSValue{A|W}.
[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 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 /* remove all messages and timers belonging to a certain window */
602 void queue_cleanup_window( struct thread *thread, user_handle_t win )
603 {
604     struct msg_queue *queue = thread->queue;
605     struct timer *timer;
606     struct message *msg;
607     int i;
608
609     if (!queue) return;
610
611     /* remove timers */
612     timer = queue->first_timer;
613     while (timer)
614     {
615         struct timer *next = timer->next;
616         if (timer->win == win)
617         {
618             unlink_timer( queue, timer );
619             free( timer );
620         }
621         timer = next;
622     }
623
624     /* remove messages */
625     for (i = 0; i < NB_MSG_KINDS; i++)
626     {
627         msg = queue->msg_list[i].first;
628         while (msg)
629         {
630             struct message *next = msg->next;
631             if (msg->win == win) remove_queue_message( queue, msg, i );
632             msg = next;
633         }
634     }
635 }
636
637 /* get the message queue of the current thread */
638 DECL_HANDLER(get_msg_queue)
639 {
640     struct msg_queue *queue = get_current_queue();
641
642     req->handle = 0;
643     if (queue) req->handle = alloc_handle( current->process, queue, SYNCHRONIZE, 0 );
644 }
645
646
647 /* increment the message queue paint count */
648 DECL_HANDLER(inc_queue_paint_count)
649 {
650     struct msg_queue *queue;
651     struct thread *thread = get_thread_from_id( req->id );
652
653     if (!thread) return;
654
655     if ((queue = thread->queue))
656     {
657         if ((queue->paint_count += req->incr) < 0) queue->paint_count = 0;
658
659         if (queue->paint_count)
660             set_queue_bits( queue, QS_PAINT );
661         else
662             clear_queue_bits( queue, QS_PAINT );
663     }
664     else set_error( STATUS_INVALID_PARAMETER );
665
666     release_object( thread );
667
668 }
669
670
671 /* set the current message queue wakeup mask */
672 DECL_HANDLER(set_queue_mask)
673 {
674     struct msg_queue *queue = get_current_queue();
675
676     if (queue)
677     {
678         queue->wake_mask    = req->wake_mask;
679         queue->changed_mask = req->changed_mask;
680         req->wake_bits      = queue->wake_bits;
681         req->changed_bits   = queue->changed_bits;
682         if (is_signaled( queue ))
683         {
684             /* if skip wait is set, do what would have been done in the subsequent wait */
685             if (req->skip_wait) msg_queue_satisfied( &queue->obj, current );
686             else wake_up( &queue->obj, 0 );
687         }
688     }
689 }
690
691
692 /* get the current message queue status */
693 DECL_HANDLER(get_queue_status)
694 {
695     struct msg_queue *queue = current->queue;
696     if (queue)
697     {
698         req->wake_bits    = queue->wake_bits;
699         req->changed_bits = queue->changed_bits;
700         if (req->clear) queue->changed_bits = 0;
701     }
702     else req->wake_bits = req->changed_bits = 0;
703 }
704
705
706 /* send a message to a thread queue */
707 DECL_HANDLER(send_message)
708 {
709     struct message *msg;
710     struct msg_queue *send_queue = get_current_queue();
711     struct msg_queue *recv_queue;
712     struct thread *thread = get_thread_from_id( req->id );
713
714     if (!thread) return;
715
716     if (!(recv_queue = thread->queue))
717     {
718         set_error( STATUS_INVALID_PARAMETER );
719         release_object( thread );
720         return;
721     }
722
723     if ((msg = mem_alloc( sizeof(*msg) )))
724     {
725         msg->type      = req->type;
726         msg->win       = get_user_full_handle( req->win );
727         msg->msg       = req->msg;
728         msg->wparam    = req->wparam;
729         msg->lparam    = req->lparam;
730         msg->time      = req->time;
731         msg->x         = req->x;
732         msg->y         = req->y;
733         msg->info      = req->info;
734         msg->result    = NULL;
735         msg->data      = NULL;
736         msg->data_size = 0;
737
738         switch(msg->type)
739         {
740        case MSG_OTHER_PROCESS:
741             msg->data_size = get_req_data_size(req);
742             if (msg->data_size && !(msg->data = memdup( get_req_data(req), msg->data_size )))
743             {
744                 free( msg );
745                 break;
746             }
747             /* fall through */
748         case MSG_ASCII:
749         case MSG_UNICODE:
750         case MSG_CALLBACK:
751             if (!(msg->result = alloc_message_result( send_queue, recv_queue, req->timeout )))
752             {
753                 free( msg );
754                 break;
755             }
756             /* fall through */
757         case MSG_NOTIFY:
758             append_message( &recv_queue->msg_list[SEND_MESSAGE], msg );
759             set_queue_bits( recv_queue, QS_SENDMESSAGE );
760             break;
761         case MSG_POSTED:
762             append_message( &recv_queue->msg_list[POST_MESSAGE], msg );
763             set_queue_bits( recv_queue, QS_POSTMESSAGE );
764             break;
765         case MSG_HARDWARE_RAW:
766         case MSG_HARDWARE_COOKED:
767             {
768                 struct message_list *list = ((msg->type == MSG_HARDWARE_RAW) ?
769                                              &recv_queue->msg_list[RAW_HW_MESSAGE] :
770                                              &recv_queue->msg_list[COOKED_HW_MESSAGE]);
771                 if (msg->msg == WM_MOUSEMOVE && merge_message( list, msg ))
772                 {
773                     free( msg );
774                     break;
775                 }
776                 append_message( list, msg );
777                 set_queue_bits( recv_queue, get_hardware_msg_bit(msg) );
778                 break;
779             }
780         default:
781             set_error( STATUS_INVALID_PARAMETER );
782             free( msg );
783             break;
784         }
785     }
786     release_object( thread );
787 }
788
789 /* store a message contents into the request buffer; helper for get_message */
790 inline static void put_req_message( struct get_message_request *req, const struct message *msg )
791 {
792     int len = min( get_req_data_size(req), msg->data_size );
793
794     req->type   = msg->type;
795     req->win    = msg->win;
796     req->msg    = msg->msg;
797     req->wparam = msg->wparam;
798     req->lparam = msg->lparam;
799     req->x      = msg->x;
800     req->y      = msg->y;
801     req->time   = msg->time;
802     req->info   = msg->info;
803     if (len) memcpy( get_req_data(req), msg->data, len );
804     set_req_data_size( req, len );
805 }
806
807 /* return a message to the application, removing it from the queue if needed */
808 static void return_message_to_app( struct msg_queue *queue, struct get_message_request *req,
809                                    struct message *msg, enum message_kind kind )
810 {
811     put_req_message( req, msg );
812     /* raw messages always get removed */
813     if ((msg->type == MSG_HARDWARE_RAW) || (req->flags & GET_MSG_REMOVE))
814     {
815         queue->last_msg = NULL;
816         remove_queue_message( queue, msg, kind );
817     }
818     else  /* remember it as the last returned message */
819     {
820         queue->last_msg = msg;
821         queue->last_msg_kind = kind;
822     }
823 }
824
825
826 inline static struct message *find_matching_message( const struct message_list *list,
827                                                      user_handle_t win,
828                                                      unsigned int first, unsigned int last )
829 {
830     struct message *msg;
831
832     for (msg = list->first; msg; msg = msg->next)
833     {
834         /* check against the filters */
835         if (msg->msg == WM_QUIT) break;  /* WM_QUIT is never filtered */
836         if (win && msg->win && msg->win != win && !is_child_window( win, msg->win )) continue;
837         if (msg->msg < first) continue;
838         if (msg->msg > last) continue;
839         break; /* found one */
840     }
841     return msg;
842 }
843
844
845 /* get a message from the current queue */
846 DECL_HANDLER(get_message)
847 {
848     struct timer *timer;
849     struct message *msg;
850     struct msg_queue *queue = get_current_queue();
851     user_handle_t get_win = get_user_full_handle( req->get_win );
852
853     if (!queue)
854     {
855         set_req_data_size( req, 0 );
856         return;
857     }
858
859     /* first check for sent messages */
860     if ((msg = queue->msg_list[SEND_MESSAGE].first))
861     {
862         put_req_message( req, msg );
863         receive_message( queue, msg );
864         return;
865     }
866     set_req_data_size( req, 0 ); /* only sent messages can have data */
867     if (req->flags & GET_MSG_SENT_ONLY) goto done;  /* nothing else to check */
868
869     /* if requested, remove the last returned but not yet removed message */
870     if ((req->flags & GET_MSG_REMOVE_LAST) && queue->last_msg)
871         remove_queue_message( queue, queue->last_msg, queue->last_msg_kind );
872     queue->last_msg = NULL;
873
874     /* clear changed bits so we can wait on them if we don't find a message */
875     queue->changed_bits = 0;
876
877     /* then check for posted messages */
878     if ((msg = find_matching_message( &queue->msg_list[POST_MESSAGE], get_win,
879                                       req->get_first, req->get_last )))
880     {
881         return_message_to_app( queue, req, msg, POST_MESSAGE );
882         return;
883     }
884
885     /* then check for cooked hardware messages */
886     if ((msg = find_matching_message( &queue->msg_list[COOKED_HW_MESSAGE], get_win,
887                                       req->get_first, req->get_last )))
888     {
889         return_message_to_app( queue, req, msg, COOKED_HW_MESSAGE );
890         return;
891     }
892
893     /* then check for any raw hardware message */
894     if ((msg = queue->msg_list[RAW_HW_MESSAGE].first))
895     {
896         return_message_to_app( queue, req, msg, RAW_HW_MESSAGE );
897         return;
898     }
899
900     /* now check for WM_PAINT */
901     if ((queue->wake_bits & QS_PAINT) &&
902         (WM_PAINT >= req->get_first) && (WM_PAINT <= req->get_last))
903     {
904         req->type   = MSG_POSTED;
905         req->win    = 0;
906         req->msg    = WM_PAINT;
907         req->wparam = 0;
908         req->lparam = 0;
909         req->x      = 0;
910         req->y      = 0;
911         req->time   = get_tick_count();
912         req->info   = 0;
913         return;
914     }
915
916     /* now check for timer */
917     if ((timer = find_expired_timer( queue, get_win, req->get_first,
918                                      req->get_last, (req->flags & GET_MSG_REMOVE) )))
919     {
920         req->type   = MSG_POSTED;
921         req->win    = timer->win;
922         req->msg    = timer->msg;
923         req->wparam = timer->id;
924         req->lparam = timer->lparam;
925         req->x      = 0;
926         req->y      = 0;
927         req->time   = get_tick_count();
928         req->info   = 0;
929         return;
930     }
931
932  done:
933     set_error( STATUS_PENDING );  /* FIXME */
934 }
935
936
937 /* reply to a sent message */
938 DECL_HANDLER(reply_message)
939 {
940     if (current->queue && current->queue->recv_result)
941         reply_message( current->queue, req->result, 0, req->remove,
942                        get_req_data(req), get_req_data_size(req) );
943     else
944         set_error( STATUS_ACCESS_DENIED );
945 }
946
947
948 /* retrieve the reply for the last message sent */
949 DECL_HANDLER(get_message_reply)
950 {
951     struct msg_queue *queue = current->queue;
952     size_t data_len = 0;
953
954     if (queue)
955     {
956         struct message_result *result = queue->send_result;
957
958         set_error( STATUS_PENDING );
959         req->result = 0;
960
961         if (result && (result->replied || req->cancel))
962         {
963             if (result->replied)
964             {
965                 req->result = result->result;
966                 set_error( result->error );
967                 if (result->data)
968                 {
969                     data_len = min( result->data_size, get_req_data_size(req) );
970                     memcpy( get_req_data(req), result->data, data_len );
971                     free( result->data );
972                     result->data = NULL;
973                     result->data_size = 0;
974                 }
975             }
976             queue->send_result = result->send_next;
977             result->sender = NULL;
978             if (!result->receiver) free_result( result );
979             if (!queue->send_result || !queue->send_result->replied)
980                 clear_queue_bits( queue, QS_SMRESULT );
981         }
982     }
983     else set_error( STATUS_ACCESS_DENIED );
984     set_req_data_size( req, data_len );
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     user_handle_t win = get_user_full_handle( req->win );
994
995     if (!queue) return;
996
997     /* remove it if it existed already */
998     if (win) kill_timer( queue, win, req->msg, req->id );
999
1000     if ((timer = set_timer( queue, req->rate )))
1001     {
1002         timer->win    = win;
1003         timer->msg    = req->msg;
1004         timer->id     = req->id;
1005         timer->lparam = req->lparam;
1006     }
1007 }
1008
1009 /* kill a window timer */
1010 DECL_HANDLER(kill_win_timer)
1011 {
1012     struct msg_queue *queue = current->queue;
1013
1014     if (!queue || !kill_timer( queue, get_user_full_handle(req->win), req->msg, req->id ))
1015         set_error( STATUS_INVALID_PARAMETER );
1016 }