Release 971130
[wine] / windows / queue.c
1 /*
2  * Message queues related functions
3  *
4  * Copyright 1993, 1994 Alexandre Julliard
5  */
6
7 #include <stdlib.h>
8 #include <signal.h>
9 #include "miscemu.h"
10 #include "module.h"
11 #include "queue.h"
12 #include "task.h"
13 #include "win.h"
14 #include "clipboard.h"
15 #include "hook.h"
16 #include "thread.h"
17 #include "process.h"
18 #include "stddebug.h"
19 #include "debug.h"
20
21 #define MAX_QUEUE_SIZE   120  /* Max. size of a message queue */
22
23 static HQUEUE16 hFirstQueue = 0;
24 static HQUEUE16 hExitingQueue = 0;
25 static HQUEUE16 hmemSysMsgQueue = 0;
26 static MESSAGEQUEUE *sysMsgQueue = NULL;
27
28 static MESSAGEQUEUE *pMouseQueue = NULL;  /* Queue for last mouse message */
29 static MESSAGEQUEUE *pKbdQueue = NULL;    /* Queue for last kbd message */
30
31 MESSAGEQUEUE *pCursorQueue = NULL; 
32 MESSAGEQUEUE *pActiveQueue = NULL;
33
34 /***********************************************************************
35  *           QUEUE_DumpQueue
36  */
37 void QUEUE_DumpQueue( HQUEUE16 hQueue )
38 {
39     MESSAGEQUEUE *pq; 
40
41     if (!(pq = (MESSAGEQUEUE*) GlobalLock16( hQueue )) ||
42         GlobalSize16(hQueue) < sizeof(MESSAGEQUEUE)+pq->queueSize*sizeof(QMSG))
43     {
44         fprintf( stderr, "%04x is not a queue handle\n", hQueue );
45         return;
46     }
47
48     fprintf( stderr,
49              "next: %12.4x  Intertask SendMessage:\n"
50              "hTask: %11.4x  ----------------------\n"
51              "msgSize: %9.4x  hWnd: %10.4x\n"
52              "msgCount: %8.4x  msg: %11.4x\n"
53              "msgNext: %9.4x  wParam: %8.4x\n"
54              "msgFree: %9.4x  lParam: %8.8x\n"
55              "qSize: %11.4x  lRet: %10.8x\n"
56              "wWinVer: %9.4x  ISMH: %10.4x\n"
57              "paints: %10.4x  hSendTask: %5.4x\n"
58              "timers: %10.4x  hPrevSend: %5.4x\n"
59              "wakeBits: %8.4x\n"
60              "wakeMask: %8.4x\n"
61              "hCurHook: %8.4x\n",
62              pq->next, pq->hTask, pq->msgSize, pq->hWnd, 
63              pq->msgCount, pq->msg, pq->nextMessage, pq->wParam,
64              pq->nextFreeMessage, (unsigned)pq->lParam, pq->queueSize,
65              (unsigned)pq->SendMessageReturn, pq->wWinVersion, pq->InSendMessageHandle,
66              pq->wPaintCount, pq->hSendingTask, pq->wTimerCount,
67              pq->hPrevSendingTask, pq->wakeBits, pq->wakeMask, pq->hCurHook);
68 }
69
70
71 /***********************************************************************
72  *           QUEUE_WalkQueues
73  */
74 void QUEUE_WalkQueues(void)
75 {
76     HQUEUE16 hQueue = hFirstQueue;
77
78     fprintf( stderr, "Queue Size Msgs Task\n" );
79     while (hQueue)
80     {
81         MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
82         if (!queue)
83         {
84             fprintf( stderr, "*** Bad queue handle %04x\n", hQueue );
85             return;
86         }
87         fprintf( stderr, "%04x %5d %4d %04x %s\n",
88                  hQueue, queue->msgSize, queue->msgCount, queue->hTask,
89                  MODULE_GetModuleName( queue->hTask ) );
90         hQueue = queue->next;
91     }
92     fprintf( stderr, "\n" );
93 }
94
95
96 /***********************************************************************
97  *           QUEUE_IsExitingQueue
98  */
99 BOOL32 QUEUE_IsExitingQueue( HQUEUE16 hQueue )
100 {
101     return (hExitingQueue && (hQueue == hExitingQueue));
102 }
103
104
105 /***********************************************************************
106  *           QUEUE_SetExitingQueue
107  */
108 void QUEUE_SetExitingQueue( HQUEUE16 hQueue )
109 {
110     hExitingQueue = hQueue;
111 }
112
113
114 /***********************************************************************
115  *           QUEUE_CreateMsgQueue
116  *
117  * Creates a message queue. Doesn't link it into queue list!
118  */
119 static HQUEUE16 QUEUE_CreateMsgQueue( int size )
120 {
121     HQUEUE16 hQueue;
122     MESSAGEQUEUE * msgQueue;
123     int queueSize;
124     TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
125
126     dprintf_msg(stddeb,"Creating message queue...\n");
127
128     queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
129     if (!(hQueue = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, queueSize )))
130         return 0;
131     msgQueue = (MESSAGEQUEUE *) GlobalLock16( hQueue );
132     msgQueue->self        = hQueue;
133     msgQueue->msgSize     = sizeof(QMSG);
134     msgQueue->queueSize   = size;
135     msgQueue->wakeBits    = msgQueue->changeBits = QS_SMPARAMSFREE;
136     msgQueue->wWinVersion = pTask ? pTask->version : 0;
137     GlobalUnlock16( hQueue );
138     return hQueue;
139 }
140
141
142 /***********************************************************************
143  *           QUEUE_DeleteMsgQueue
144  *
145  * Unlinks and deletes a message queue.
146  *
147  * Note: We need to mask asynchronous events to make sure PostMessage works
148  * even in the signal handler.
149  */
150 BOOL32 QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
151 {
152     MESSAGEQUEUE * msgQueue = (MESSAGEQUEUE*)GlobalLock16(hQueue);
153     HQUEUE16  senderQ;
154     HQUEUE16 *pPrev;
155
156     dprintf_msg(stddeb,"Deleting message queue %04x\n", hQueue);
157
158     if (!hQueue || !msgQueue)
159     {
160         dprintf_msg(stddeb,"DeleteMsgQueue: invalid argument.\n");
161         return 0;
162     }
163     if( pCursorQueue == msgQueue ) pCursorQueue = NULL;
164     if( pActiveQueue == msgQueue ) pActiveQueue = NULL;
165
166     /* flush sent messages */
167     senderQ = msgQueue->hSendingTask;
168     while( senderQ )
169     {
170       MESSAGEQUEUE* sq = (MESSAGEQUEUE*)GlobalLock16(senderQ);
171       if( !sq ) break;
172       sq->SendMessageReturn = 0L;
173       QUEUE_SetWakeBit( sq, QS_SMRESULT );
174       senderQ = sq->hPrevSendingTask;
175     }
176
177     SIGNAL_MaskAsyncEvents( TRUE );
178
179     pPrev = &hFirstQueue;
180     while (*pPrev && (*pPrev != hQueue))
181     {
182         MESSAGEQUEUE *msgQ = (MESSAGEQUEUE*)GlobalLock16(*pPrev);
183         pPrev = &msgQ->next;
184     }
185     if (*pPrev) *pPrev = msgQueue->next;
186     msgQueue->self = 0;
187
188     SIGNAL_MaskAsyncEvents( FALSE );
189
190     GlobalFree16( hQueue );
191     return 1;
192 }
193
194
195 /***********************************************************************
196  *           QUEUE_CreateSysMsgQueue
197  *
198  * Create the system message queue, and set the double-click speed.
199  * Must be called only once.
200  */
201 BOOL32 QUEUE_CreateSysMsgQueue( int size )
202 {
203     if (size > MAX_QUEUE_SIZE) size = MAX_QUEUE_SIZE;
204     else if (size <= 0) size = 1;
205     if (!(hmemSysMsgQueue = QUEUE_CreateMsgQueue( size ))) return FALSE;
206     sysMsgQueue = (MESSAGEQUEUE *) GlobalLock16( hmemSysMsgQueue );
207     return TRUE;
208 }
209
210
211 /***********************************************************************
212  *           QUEUE_GetSysQueue
213  */
214 MESSAGEQUEUE *QUEUE_GetSysQueue(void)
215 {
216     return sysMsgQueue;
217 }
218
219
220 /***********************************************************************
221  *           QUEUE_SetWakeBit
222  *
223  * See "Windows Internals", p.449
224  */
225 void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit )
226 {
227     dprintf_msg(stddeb,"SetWakeBit: queue = %04x (wm=%04x), bit = %04x\n", 
228                         queue->self, queue->wakeMask, bit );
229
230     if (bit & QS_MOUSE) pMouseQueue = queue;
231     if (bit & QS_KEY) pKbdQueue = queue;
232     queue->changeBits |= bit;
233     queue->wakeBits   |= bit;
234     if (queue->wakeMask & bit)
235     {
236         queue->wakeMask = 0;
237         PostEvent( queue->hTask );
238     }
239 }
240
241
242 /***********************************************************************
243  *           QUEUE_ClearWakeBit
244  */
245 void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit )
246 {
247     queue->changeBits &= ~bit;
248     queue->wakeBits   &= ~bit;
249 }
250
251
252 /***********************************************************************
253  *           QUEUE_WaitBits
254  *
255  * See "Windows Internals", p.447
256  */
257 void QUEUE_WaitBits( WORD bits )
258 {
259     MESSAGEQUEUE *queue;
260
261     dprintf_msg(stddeb,"WaitBits: q %04x waiting for %04x\n", GetTaskQueue(0), bits);
262
263     for (;;)
264     {
265         if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return;
266
267         if (queue->changeBits & bits)
268         {
269             /* One of the bits is set; we can return */
270             queue->wakeMask = 0;
271             return;
272         }
273         if (queue->wakeBits & QS_SENDMESSAGE)
274         {
275             /* Process the sent message immediately */
276
277             queue->wakeMask = 0;
278             QUEUE_ReceiveMessage( queue );
279             continue;                           /* nested sm crux */
280         }
281
282         queue->wakeMask = bits | QS_SENDMESSAGE;
283         if(queue->changeBits & bits) continue;
284         
285         dprintf_msg(stddeb,"wb: (%04x) wakeMask is %04x, waiting\n", queue->self, queue->wakeMask);
286
287         WaitEvent( 0 );
288     }
289 }
290
291
292 /***********************************************************************
293  *           QUEUE_ReceiveMessage
294  *
295  * This routine is called when a sent message is waiting for the queue.
296  */
297 void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue )
298 {
299     MESSAGEQUEUE *senderQ = NULL;
300     HQUEUE16      prevSender = 0;
301     QSMCTRL*      prevCtrlPtr = NULL;
302     LRESULT       result = 0;
303
304     dprintf_msg(stddeb, "ReceiveMessage, queue %04x\n", queue->self );
305     if (!(queue->wakeBits & QS_SENDMESSAGE) ||
306         !(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask))) 
307         { dprintf_msg(stddeb,"\trcm: nothing to do\n"); return; }
308
309     if( !senderQ->hPrevSendingTask )
310     {
311       queue->wakeBits &= ~QS_SENDMESSAGE;       /* no more sent messages */
312       queue->changeBits &= ~QS_SENDMESSAGE;
313     }
314
315     /* Save current state on stack */
316     prevSender                 = queue->InSendMessageHandle;
317     prevCtrlPtr                = queue->smResultCurrent;
318
319     /* Remove sending queue from the list */
320     queue->InSendMessageHandle = queue->hSendingTask;
321     queue->smResultCurrent     = senderQ->smResultInit;
322     queue->hSendingTask        = senderQ->hPrevSendingTask;
323
324     dprintf_msg(stddeb, "\trcm: smResultCurrent = %08x, prevCtrl = %08x\n", 
325                                 (unsigned)queue->smResultCurrent, (unsigned)prevCtrlPtr );
326     QUEUE_SetWakeBit( senderQ, QS_SMPARAMSFREE );
327
328     dprintf_msg(stddeb, "\trcm: calling wndproc - %04x %04x %04x%04x %08x\n",
329                 senderQ->hWnd, senderQ->msg, senderQ->wParamHigh,
330                 senderQ->wParam, (unsigned)senderQ->lParam );
331
332     if (IsWindow32( senderQ->hWnd ))
333     {
334         WND *wndPtr = WIN_FindWndPtr( senderQ->hWnd );
335         DWORD extraInfo = queue->GetMessageExtraInfoVal;
336         queue->GetMessageExtraInfoVal = senderQ->GetMessageExtraInfoVal;
337
338         if (senderQ->flags & QUEUE_SM_WIN32)
339         {
340             WPARAM32 wParam = MAKELONG( senderQ->wParam, senderQ->wParamHigh );
341             dprintf_msg(stddeb, "\trcm: msg is Win32\n" );
342             if (senderQ->flags & QUEUE_SM_UNICODE)
343                 result = CallWindowProc32W( wndPtr->winproc,
344                                             senderQ->hWnd, senderQ->msg,
345                                             wParam, senderQ->lParam );
346             else
347                 result = CallWindowProc32A( wndPtr->winproc,
348                                             senderQ->hWnd, senderQ->msg,
349                                             wParam, senderQ->lParam );
350         }
351         else  /* Win16 message */
352             result = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
353                                        senderQ->hWnd, senderQ->msg,
354                                        senderQ->wParam, senderQ->lParam );
355
356         queue->GetMessageExtraInfoVal = extraInfo;  /* Restore extra info */
357         dprintf_msg(stddeb,"\trcm: result =  %08x\n", (unsigned)result );
358     }
359     else dprintf_msg(stddeb,"\trcm: bad hWnd\n");
360
361     /* Return the result to the sender task */
362     ReplyMessage16( result );
363
364     queue->InSendMessageHandle = prevSender;
365     queue->smResultCurrent     = prevCtrlPtr;
366
367     dprintf_msg(stddeb,"ReceiveMessage: done!\n");
368 }
369
370 /***********************************************************************
371  *           QUEUE_FlushMessage
372  * 
373  * Try to reply to all pending sent messages on exit.
374  */
375 void QUEUE_FlushMessages( HQUEUE16 hQueue )
376 {
377   MESSAGEQUEUE *queue = (MESSAGEQUEUE*)GlobalLock16( hQueue );
378
379   if( queue )
380   {
381     MESSAGEQUEUE *senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask);
382     QSMCTRL*      CtrlPtr = queue->smResultCurrent;
383
384     while( senderQ )
385     {
386       if( !(queue->hSendingTask = senderQ->hPrevSendingTask) )
387             queue->wakeBits &= ~QS_SENDMESSAGE;
388       QUEUE_SetWakeBit( senderQ, QS_SMPARAMSFREE );
389       
390       queue->smResultCurrent = CtrlPtr;
391       while( senderQ->wakeBits & QS_SMRESULT ) OldYield();
392
393       senderQ->SendMessageReturn = 0;
394       senderQ->smResult = queue->smResultCurrent;
395       QUEUE_SetWakeBit( senderQ, QS_SMRESULT);
396
397       if( (senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask)) )
398            CtrlPtr = senderQ->smResultInit;
399     }
400     queue->InSendMessageHandle = 0;
401   }  
402 }
403
404 /***********************************************************************
405  *           QUEUE_AddMsg
406  *
407  * Add a message to the queue. Return FALSE if queue is full.
408  */
409 BOOL32 QUEUE_AddMsg( HQUEUE16 hQueue, MSG16 * msg, DWORD extraInfo )
410 {
411     int pos;
412     MESSAGEQUEUE *msgQueue;
413
414     SIGNAL_MaskAsyncEvents( TRUE );
415
416     if (!(msgQueue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return FALSE;
417     pos = msgQueue->nextFreeMessage;
418
419       /* Check if queue is full */
420     if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0))
421     {
422         SIGNAL_MaskAsyncEvents( FALSE );
423         fprintf(stderr,"MSG_AddMsg // queue is full !\n");
424         return FALSE;
425     }
426
427       /* Store message */
428     msgQueue->messages[pos].msg = *msg;
429     msgQueue->messages[pos].extraInfo = extraInfo;
430     if (pos < msgQueue->queueSize-1) pos++;
431     else pos = 0;
432     msgQueue->nextFreeMessage = pos;
433     msgQueue->msgCount++;
434
435     SIGNAL_MaskAsyncEvents( FALSE );
436
437     QUEUE_SetWakeBit( msgQueue, QS_POSTMESSAGE );
438     return TRUE;
439 }
440
441
442 /***********************************************************************
443  *           QUEUE_FindMsg
444  *
445  * Find a message matching the given parameters. Return -1 if none available.
446  */
447 int QUEUE_FindMsg( MESSAGEQUEUE * msgQueue, HWND32 hwnd, int first, int last )
448 {
449     int i, pos = msgQueue->nextMessage;
450
451     dprintf_msg(stddeb,"QUEUE_FindMsg: hwnd=%04x pos=%d\n", hwnd, pos );
452
453     if (!msgQueue->msgCount) return -1;
454     if (!hwnd && !first && !last) return pos;
455         
456     for (i = 0; i < msgQueue->msgCount; i++)
457     {
458         MSG16 * msg = &msgQueue->messages[pos].msg;
459
460         if (!hwnd || (msg->hwnd == hwnd))
461         {
462             if (!first && !last) return pos;
463             if ((msg->message >= first) && (msg->message <= last)) return pos;
464         }
465         if (pos < msgQueue->queueSize-1) pos++;
466         else pos = 0;
467     }
468     return -1;
469 }
470
471
472 /***********************************************************************
473  *           QUEUE_RemoveMsg
474  *
475  * Remove a message from the queue (pos must be a valid position).
476  */
477 void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, int pos )
478 {
479     SIGNAL_MaskAsyncEvents( TRUE );
480
481     if (pos >= msgQueue->nextMessage)
482     {
483         for ( ; pos > msgQueue->nextMessage; pos--)
484             msgQueue->messages[pos] = msgQueue->messages[pos-1];
485         msgQueue->nextMessage++;
486         if (msgQueue->nextMessage >= msgQueue->queueSize)
487             msgQueue->nextMessage = 0;
488     }
489     else
490     {
491         for ( ; pos < msgQueue->nextFreeMessage; pos++)
492             msgQueue->messages[pos] = msgQueue->messages[pos+1];
493         if (msgQueue->nextFreeMessage) msgQueue->nextFreeMessage--;
494         else msgQueue->nextFreeMessage = msgQueue->queueSize-1;
495     }
496     msgQueue->msgCount--;
497     if (!msgQueue->msgCount) msgQueue->wakeBits &= ~QS_POSTMESSAGE;
498
499     SIGNAL_MaskAsyncEvents( FALSE );
500 }
501
502
503 /***********************************************************************
504  *           QUEUE_WakeSomeone
505  *
506  * Wake a queue upon reception of a hardware event.
507  */
508 static void QUEUE_WakeSomeone( UINT32 message )
509 {
510     WND*          wndPtr = NULL;
511     WORD          wakeBit;
512     HWND32 hwnd;
513     MESSAGEQUEUE *queue = pCursorQueue;
514
515     if( (message >= WM_KEYFIRST) && (message <= WM_KEYLAST) )
516     {
517        wakeBit = QS_KEY;
518        if( pActiveQueue ) queue = pActiveQueue;
519     }
520     else 
521     {
522        wakeBit = (message == WM_MOUSEMOVE) ? QS_MOUSEMOVE : QS_MOUSEBUTTON;
523        if( (hwnd = GetCapture32()) )
524          if( (wndPtr = WIN_FindWndPtr( hwnd )) ) 
525            queue = (MESSAGEQUEUE *)GlobalLock16( wndPtr->hmemTaskQ );
526     }
527
528     if( (hwnd = GetSysModalWindow16()) )
529       if( (wndPtr = WIN_FindWndPtr( hwnd )) )
530         queue = (MESSAGEQUEUE *)GlobalLock16( wndPtr->hmemTaskQ );
531
532     if( !queue ) 
533     {
534       queue = GlobalLock16( hFirstQueue );
535       while( queue )
536       {
537         if (queue->wakeMask & wakeBit) break;
538         queue = GlobalLock16( queue->next );
539       }
540       if( !queue )
541       { 
542         dprintf_msg(stddeb,"WakeSomeone: couldn't find queue\n"); 
543         return; 
544       }
545     }
546
547     QUEUE_SetWakeBit( queue, wakeBit );
548 }
549
550
551 /***********************************************************************
552  *           hardware_event
553  *
554  * Add an event to the system message queue.
555  * Note: the position is relative to the desktop window.
556  */
557 void hardware_event( WORD message, WORD wParam, LONG lParam,
558                      int xPos, int yPos, DWORD time, DWORD extraInfo )
559 {
560     MSG16 *msg;
561     int pos;
562
563     if (!sysMsgQueue) return;
564     pos = sysMsgQueue->nextFreeMessage;
565
566       /* Merge with previous event if possible */
567
568     if ((message == WM_MOUSEMOVE) && sysMsgQueue->msgCount)
569     {
570         if (pos > 0) pos--;
571         else pos = sysMsgQueue->queueSize - 1;
572         msg = &sysMsgQueue->messages[pos].msg;
573         if ((msg->message == message) && (msg->wParam == wParam))
574             sysMsgQueue->msgCount--;  /* Merge events */
575         else
576             pos = sysMsgQueue->nextFreeMessage;  /* Don't merge */
577     }
578
579       /* Check if queue is full */
580
581     if ((pos == sysMsgQueue->nextMessage) && sysMsgQueue->msgCount)
582     {
583         /* Queue is full, beep (but not on every mouse motion...) */
584         if (message != WM_MOUSEMOVE) MessageBeep32(0);
585         return;
586     }
587
588       /* Store message */
589
590     msg = &sysMsgQueue->messages[pos].msg;
591     msg->hwnd    = 0;
592     msg->message = message;
593     msg->wParam  = wParam;
594     msg->lParam  = lParam;
595     msg->time    = time;
596     msg->pt.x    = xPos & 0xffff;
597     msg->pt.y    = yPos & 0xffff;
598     sysMsgQueue->messages[pos].extraInfo = extraInfo;
599     if (pos < sysMsgQueue->queueSize - 1) pos++;
600     else pos = 0;
601     sysMsgQueue->nextFreeMessage = pos;
602     sysMsgQueue->msgCount++;
603     QUEUE_WakeSomeone( message );
604 }
605
606                     
607 /***********************************************************************
608  *           QUEUE_GetQueueTask
609  */
610 HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue )
611 {
612     MESSAGEQUEUE *queue = GlobalLock16( hQueue );
613     return (queue) ? queue->hTask : 0 ;
614 }
615
616
617 /***********************************************************************
618  *           QUEUE_IncPaintCount
619  */
620 void QUEUE_IncPaintCount( HQUEUE16 hQueue )
621 {
622     MESSAGEQUEUE *queue;
623
624     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
625     queue->wPaintCount++;
626     QUEUE_SetWakeBit( queue, QS_PAINT );
627 }
628
629
630 /***********************************************************************
631  *           QUEUE_DecPaintCount
632  */
633 void QUEUE_DecPaintCount( HQUEUE16 hQueue )
634 {
635     MESSAGEQUEUE *queue;
636
637     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
638     queue->wPaintCount--;
639     if (!queue->wPaintCount) queue->wakeBits &= ~QS_PAINT;
640 }
641
642
643 /***********************************************************************
644  *           QUEUE_IncTimerCount
645  */
646 void QUEUE_IncTimerCount( HQUEUE16 hQueue )
647 {
648     MESSAGEQUEUE *queue;
649
650     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
651     queue->wTimerCount++;
652     QUEUE_SetWakeBit( queue, QS_TIMER );
653 }
654
655
656 /***********************************************************************
657  *           QUEUE_DecTimerCount
658  */
659 void QUEUE_DecTimerCount( HQUEUE16 hQueue )
660 {
661     MESSAGEQUEUE *queue;
662
663     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
664     queue->wTimerCount--;
665     if (!queue->wTimerCount) queue->wakeBits &= ~QS_TIMER;
666 }
667
668
669 /***********************************************************************
670  *           PostQuitMessage16   (USER.6)
671  */
672 void WINAPI PostQuitMessage16( INT16 exitCode )
673 {
674     PostQuitMessage32( exitCode );
675 }
676
677
678 /***********************************************************************
679  *           PostQuitMessage32   (USER32.420)
680  */
681 void WINAPI PostQuitMessage32( INT32 exitCode )
682 {
683     MESSAGEQUEUE *queue;
684
685     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return;
686     queue->wPostQMsg = TRUE;
687     queue->wExitCode = (WORD)exitCode;
688 }
689
690
691 /***********************************************************************
692  *           GetWindowTask16   (USER.224)
693  */
694 HTASK16 WINAPI GetWindowTask16( HWND16 hwnd )
695 {
696     WND *wndPtr = WIN_FindWndPtr( hwnd );
697
698     if (!wndPtr) return 0;
699     return QUEUE_GetQueueTask( wndPtr->hmemTaskQ );
700 }
701
702 /***********************************************************************
703  *           GetWindowThreadProcessId   (USER32.312)
704  */
705 DWORD WINAPI GetWindowThreadProcessId( HWND32 hwnd, LPDWORD process )
706 {
707     HTASK16 htask;
708     TDB *tdb;
709
710     WND *wndPtr = WIN_FindWndPtr( hwnd );
711
712     if (!wndPtr) return 0;
713     htask=QUEUE_GetQueueTask( wndPtr->hmemTaskQ );
714     tdb = (TDB*)GlobalLock16(htask);
715     if (!tdb) return 0;
716     if (tdb->thdb) {
717         if (process)
718                 *process = (DWORD)tdb->thdb->process;
719         return (DWORD)tdb->thdb;
720     }
721     return 0;
722
723 }
724
725
726 /***********************************************************************
727  *           SetMessageQueue16   (USER.266)
728  */
729 BOOL16 WINAPI SetMessageQueue16( INT16 size )
730 {
731     return SetMessageQueue32( size );
732 }
733
734
735 /***********************************************************************
736  *           SetMessageQueue32   (USER32.493)
737  */
738 BOOL32 WINAPI SetMessageQueue32( INT32 size )
739 {
740     HQUEUE16 hQueue, hNewQueue;
741     MESSAGEQUEUE *queuePtr;
742
743     dprintf_msg(stddeb,"SetMessageQueue: task %04x size %i\n", GetCurrentTask(), size); 
744
745     if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return TRUE;
746
747     if( !(hNewQueue = QUEUE_CreateMsgQueue( size ))) 
748     {
749         dprintf_msg(stddeb,"SetMessageQueue: failed!\n");
750         return FALSE;
751     }
752     queuePtr = (MESSAGEQUEUE *)GlobalLock16( hNewQueue );
753
754     SIGNAL_MaskAsyncEvents( TRUE );
755
756     /* Copy data and free the old message queue */
757     if ((hQueue = GetTaskQueue(0)) != 0) 
758     {
759        MESSAGEQUEUE *oldQ = (MESSAGEQUEUE *)GlobalLock16( hQueue );
760        memcpy( &queuePtr->wParamHigh, &oldQ->wParamHigh,
761                         (int)oldQ->messages - (int)(&oldQ->wParamHigh) );
762        HOOK_ResetQueueHooks( hNewQueue );
763        if( WIN_GetDesktop()->hmemTaskQ == hQueue )
764            WIN_GetDesktop()->hmemTaskQ = hNewQueue;
765        WIN_ResetQueueWindows( WIN_GetDesktop(), hQueue, hNewQueue );
766        CLIPBOARD_ResetLock( hQueue, hNewQueue );
767        QUEUE_DeleteMsgQueue( hQueue );
768     }
769
770     /* Link new queue into list */
771     queuePtr->hTask = GetCurrentTask();
772     queuePtr->next  = hFirstQueue;
773     hFirstQueue = hNewQueue;
774     
775     if( !queuePtr->next ) pCursorQueue = queuePtr;
776     SetTaskQueue( 0, hNewQueue );
777     
778     SIGNAL_MaskAsyncEvents( FALSE );
779     return TRUE;
780 }
781
782
783 /***********************************************************************
784  *           GetQueueStatus16   (USER.334)
785  */
786 DWORD WINAPI GetQueueStatus16( UINT16 flags )
787 {
788     MESSAGEQUEUE *queue;
789     DWORD ret;
790
791     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
792     ret = MAKELONG( queue->changeBits, queue->wakeBits );
793     queue->changeBits = 0;
794     return ret & MAKELONG( flags, flags );
795 }
796
797 /***********************************************************************
798  *           GetQueueStatus32   (USER32.283)
799  */
800 DWORD WINAPI GetQueueStatus32( UINT32 flags )
801 {
802     MESSAGEQUEUE *queue;
803     DWORD ret;
804
805     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
806     ret = MAKELONG( queue->changeBits, queue->wakeBits );
807     queue->changeBits = 0;
808     return ret & MAKELONG( flags, flags );
809 }
810
811
812 /***********************************************************************
813  *           GetInputState16   (USER.335)
814  */
815 BOOL16 WINAPI GetInputState16(void)
816 {
817     return GetInputState32();
818 }
819
820
821 /***********************************************************************
822  *           GetInputState32   (USER32.243)
823  */
824 BOOL32 WINAPI GetInputState32(void)
825 {
826     MESSAGEQUEUE *queue;
827
828     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) )))
829         return FALSE;
830     return queue->wakeBits & (QS_KEY | QS_MOUSEBUTTON);
831 }
832
833
834 /***********************************************************************
835  *           GetMessagePos   (USER.119) (USER32.271)
836  */
837 DWORD WINAPI GetMessagePos(void)
838 {
839     MESSAGEQUEUE *queue;
840
841     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
842     return queue->GetMessagePosVal;
843 }
844
845
846 /***********************************************************************
847  *           GetMessageTime   (USER.120) (USER32.272)
848  */
849 LONG WINAPI GetMessageTime(void)
850 {
851     MESSAGEQUEUE *queue;
852
853     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
854     return queue->GetMessageTimeVal;
855 }
856
857
858 /***********************************************************************
859  *           GetMessageExtraInfo   (USER.288) (USER32.270)
860  */
861 LONG WINAPI GetMessageExtraInfo(void)
862 {
863     MESSAGEQUEUE *queue;
864
865     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
866     return queue->GetMessageExtraInfoVal;
867 }