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