2 * Message queues related functions
4 * Copyright 1993, 1994 Alexandre Julliard
14 #include "clipboard.h"
21 #define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
23 static HQUEUE16 hFirstQueue
= 0;
24 static HQUEUE16 hExitingQueue
= 0;
25 static HQUEUE16 hmemSysMsgQueue
= 0;
26 static MESSAGEQUEUE
*sysMsgQueue
= NULL
;
28 static MESSAGEQUEUE
*pMouseQueue
= NULL
; /* Queue for last mouse message */
29 static MESSAGEQUEUE
*pKbdQueue
= NULL
; /* Queue for last kbd message */
31 HQUEUE16 hCursorQueue
= 0;
32 HQUEUE16 hActiveQueue
= 0;
35 /***********************************************************************
38 * Fonction for getting a 32 bit pointer on queue strcture. For thread
39 * safeness programmers should use this function instead of GlobalLock to
40 * retrieve a pointer on the structure. QUEUE_Unlock should also be called
41 * when access to the queue structure is not required anymore.
43 MESSAGEQUEUE
*QUEUE_Lock( HQUEUE16 hQueue
)
48 queue
= GlobalLock16( hQueue
);
49 if ( !queue
|| (queue
->magic
!= QUEUE_MAGIC
) )
61 /***********************************************************************
64 * Use with QUEUE_Lock to get a thread safe acces to message queue
67 void QUEUE_Unlock( MESSAGEQUEUE
*queue
)
73 if ( --queue
->lockCount
== 0 )
75 DeleteCriticalSection ( &queue
->cSection
);
76 GlobalFree16( queue
->self
);
84 /***********************************************************************
87 void QUEUE_DumpQueue( HQUEUE16 hQueue
)
91 if (!(pq
= (MESSAGEQUEUE
*) QUEUE_Lock( hQueue
)) )
93 WARN(msg
, "%04x is not a queue handle\n", hQueue
);
97 DUMP( "next: %12.4x Intertask SendMessage:\n"
98 "thread: %10p ----------------------\n"
100 "firstMsg: %8p msg: %11.8x\n"
101 "lastMsg: %8p wParam: %10.8x\n"
102 "msgCount: %8.4x lParam: %10.8x\n"
103 "lockCount: %7.4x lRet: %12.8x\n"
104 "wWinVer: %9.4x ISMH: %10.4x\n"
105 "paints: %10.4x hSendTask: %5.4x\n"
106 "timers: %10.4x hPrevSend: %5.4x\n"
110 pq
->next
, pq
->thdb
, pq
->hWnd32
, pq
->firstMsg
, pq
->msg32
,
111 pq
->lastMsg
, pq
->wParam32
, pq
->msgCount
, (unsigned)pq
->lParam
,
112 (unsigned)pq
->lockCount
, (unsigned)pq
->SendMessageReturn
,
113 pq
->wWinVersion
, pq
->InSendMessageHandle
,
114 pq
->wPaintCount
, pq
->hSendingTask
, pq
->wTimerCount
,
115 pq
->hPrevSendingTask
, pq
->wakeBits
, pq
->wakeMask
, pq
->hCurHook
);
121 /***********************************************************************
124 void QUEUE_WalkQueues(void)
127 HQUEUE16 hQueue
= hFirstQueue
;
129 DUMP( "Queue Msgs Thread Task Module\n" );
132 MESSAGEQUEUE
*queue
= (MESSAGEQUEUE
*)QUEUE_Lock( hQueue
);
135 WARN( msg
, "Bad queue handle %04x\n", hQueue
);
138 if (!GetModuleName( queue
->thdb
->process
->task
, module
, sizeof(module
)))
139 strcpy( module
, "???" );
140 DUMP( "%04x %4d %p %04x %s\n", hQueue
,queue
->msgCount
,
141 queue
->thdb
, queue
->thdb
->process
->task
, module
);
142 hQueue
= queue
->next
;
143 QUEUE_Unlock( queue
);
149 /***********************************************************************
150 * QUEUE_IsExitingQueue
152 BOOL32
QUEUE_IsExitingQueue( HQUEUE16 hQueue
)
154 return (hExitingQueue
&& (hQueue
== hExitingQueue
));
158 /***********************************************************************
159 * QUEUE_SetExitingQueue
161 void QUEUE_SetExitingQueue( HQUEUE16 hQueue
)
163 hExitingQueue
= hQueue
;
167 /***********************************************************************
168 * QUEUE_CreateMsgQueue
170 * Creates a message queue. Doesn't link it into queue list!
172 static HQUEUE16
QUEUE_CreateMsgQueue( )
175 MESSAGEQUEUE
* msgQueue
;
176 TDB
*pTask
= (TDB
*)GlobalLock16( GetCurrentTask() );
178 TRACE(msg
,"Creating message queue...\n");
180 if (!(hQueue
= GlobalAlloc16( GMEM_FIXED
| GMEM_ZEROINIT
,
181 sizeof(MESSAGEQUEUE
) )))
184 msgQueue
= (MESSAGEQUEUE
*) GlobalLock16( hQueue
);
188 msgQueue
->self
= hQueue
;
189 msgQueue
->wakeBits
= msgQueue
->changeBits
= QS_SMPARAMSFREE
;
190 msgQueue
->wWinVersion
= pTask
? pTask
->version
: 0;
192 InitializeCriticalSection( &msgQueue
->cSection
);
193 msgQueue
->lockCount
= 1;
194 msgQueue
->magic
= QUEUE_MAGIC
;
200 /***********************************************************************
201 * QUEUE_DeleteMsgQueue
203 * Unlinks and deletes a message queue.
205 * Note: We need to mask asynchronous events to make sure PostMessage works
206 * even in the signal handler.
208 BOOL32
QUEUE_DeleteMsgQueue( HQUEUE16 hQueue
)
210 MESSAGEQUEUE
* msgQueue
= (MESSAGEQUEUE
*)QUEUE_Lock(hQueue
);
214 TRACE(msg
,"Deleting message queue %04x\n", hQueue
);
216 if (!hQueue
|| !msgQueue
)
218 WARN(msg
, "invalid argument.\n");
224 if( hCursorQueue
== hQueue
) hCursorQueue
= 0;
225 if( hActiveQueue
== hQueue
) hActiveQueue
= 0;
227 /* flush sent messages */
228 senderQ
= msgQueue
->hSendingTask
;
231 MESSAGEQUEUE
* sq
= (MESSAGEQUEUE
*)QUEUE_Lock(senderQ
);
233 sq
->SendMessageReturn
= 0L;
234 QUEUE_SetWakeBit( sq
, QS_SMRESULT
);
235 senderQ
= sq
->hPrevSendingTask
;
241 /* remove the message queue from the global link list */
242 pPrev
= &hFirstQueue
;
243 while (*pPrev
&& (*pPrev
!= hQueue
))
245 MESSAGEQUEUE
*msgQ
= (MESSAGEQUEUE
*)GlobalLock16(*pPrev
);
248 if (*pPrev
) *pPrev
= msgQueue
->next
;
253 /* free up resource used by MESSAGEQUEUE strcture */
254 msgQueue
->lockCount
--;
255 QUEUE_Unlock( msgQueue
);
261 /***********************************************************************
262 * QUEUE_CreateSysMsgQueue
264 * Create the system message queue, and set the double-click speed.
265 * Must be called only once.
267 BOOL32
QUEUE_CreateSysMsgQueue( int size
)
269 if (!(hmemSysMsgQueue
= QUEUE_CreateMsgQueue( ))) return FALSE
;
270 sysMsgQueue
= (MESSAGEQUEUE
*) GlobalLock16( hmemSysMsgQueue
);
275 /***********************************************************************
278 MESSAGEQUEUE
*QUEUE_GetSysQueue(void)
283 /***********************************************************************
286 void QUEUE_Signal( THDB
*thdb
)
288 /* Wake up thread waiting for message */
289 SetEvent( thdb
->event
);
291 PostEvent( thdb
->process
->task
);
294 /***********************************************************************
297 static void QUEUE_Wait( DWORD wait_mask
)
299 if ( THREAD_IsWin16( THREAD_Current() ) )
303 TRACE(msg
, "current task is 32-bit, calling SYNC_DoWait\n");
304 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, INFINITE32
, wait_mask
);
309 /***********************************************************************
312 * See "Windows Internals", p.449
314 void QUEUE_SetWakeBit( MESSAGEQUEUE
*queue
, WORD bit
)
316 TRACE(msg
,"queue = %04x (wm=%04x), bit = %04x\n",
317 queue
->self
, queue
->wakeMask
, bit
);
319 if (bit
& QS_MOUSE
) pMouseQueue
= queue
;
320 if (bit
& QS_KEY
) pKbdQueue
= queue
;
321 queue
->changeBits
|= bit
;
322 queue
->wakeBits
|= bit
;
323 if (queue
->wakeMask
& bit
)
326 QUEUE_Signal( queue
->thdb
);
331 /***********************************************************************
334 void QUEUE_ClearWakeBit( MESSAGEQUEUE
*queue
, WORD bit
)
336 queue
->changeBits
&= ~bit
;
337 queue
->wakeBits
&= ~bit
;
341 /***********************************************************************
344 * See "Windows Internals", p.447
346 void QUEUE_WaitBits( WORD bits
)
350 TRACE(msg
,"q %04x waiting for %04x\n", GetFastQueue(), bits
);
354 if (!(queue
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue() ))) return;
356 if (queue
->changeBits
& bits
)
358 /* One of the bits is set; we can return */
360 QUEUE_Unlock( queue
);
363 if (queue
->wakeBits
& QS_SENDMESSAGE
)
365 /* Process the sent message immediately */
368 QUEUE_ReceiveMessage( queue
);
369 QUEUE_Unlock( queue
);
370 continue; /* nested sm crux */
373 queue
->wakeMask
= bits
| QS_SENDMESSAGE
;
374 if(queue
->changeBits
& bits
)
376 QUEUE_Unlock( queue
);
380 TRACE(msg
,"%04x) wakeMask is %04x, waiting\n", queue
->self
, queue
->wakeMask
);
382 QUEUE_Wait( queue
->wakeMask
);
384 QUEUE_Unlock( queue
);
389 /***********************************************************************
390 * QUEUE_ReceiveMessage
392 * This routine is called when a sent message is waiting for the queue.
394 void QUEUE_ReceiveMessage( MESSAGEQUEUE
*queue
)
396 MESSAGEQUEUE
*senderQ
= NULL
;
397 HQUEUE16 prevSender
= 0;
398 QSMCTRL
* prevCtrlPtr
= NULL
;
401 TRACE(msg
, "ReceiveMessage, queue %04x\n", queue
->self
);
402 if (!(queue
->wakeBits
& QS_SENDMESSAGE
) ||
403 !(senderQ
= (MESSAGEQUEUE
*)QUEUE_Lock( queue
->hSendingTask
)))
404 { TRACE(msg
,"\trcm: nothing to do\n"); return; }
406 if( !senderQ
->hPrevSendingTask
)
407 QUEUE_ClearWakeBit( queue
, QS_SENDMESSAGE
); /* no more sent messages */
409 /* Save current state on stack */
410 prevSender
= queue
->InSendMessageHandle
;
411 prevCtrlPtr
= queue
->smResultCurrent
;
413 /* Remove sending queue from the list */
414 queue
->InSendMessageHandle
= queue
->hSendingTask
;
415 queue
->smResultCurrent
= senderQ
->smResultInit
;
416 queue
->hSendingTask
= senderQ
->hPrevSendingTask
;
418 TRACE(msg
, "\trcm: smResultCurrent = %08x, prevCtrl = %08x\n",
419 (unsigned)queue
->smResultCurrent
, (unsigned)prevCtrlPtr
);
420 QUEUE_SetWakeBit( senderQ
, QS_SMPARAMSFREE
);
422 TRACE(msg
, "\trcm: calling wndproc - %08x %08x %08x %08x\n",
423 senderQ
->hWnd32
, senderQ
->msg32
,
424 senderQ
->wParam32
, (unsigned)senderQ
->lParam
);
426 if (IsWindow32( senderQ
->hWnd32
))
428 WND
*wndPtr
= WIN_FindWndPtr( senderQ
->hWnd32
);
429 DWORD extraInfo
= queue
->GetMessageExtraInfoVal
;
430 queue
->GetMessageExtraInfoVal
= senderQ
->GetMessageExtraInfoVal
;
432 if (senderQ
->flags
& QUEUE_SM_WIN32
)
434 TRACE(msg
, "\trcm: msg is Win32\n" );
435 if (senderQ
->flags
& QUEUE_SM_UNICODE
)
436 result
= CallWindowProc32W( wndPtr
->winproc
,
437 senderQ
->hWnd32
, senderQ
->msg32
,
438 senderQ
->wParam32
, senderQ
->lParam
);
440 result
= CallWindowProc32A( wndPtr
->winproc
,
441 senderQ
->hWnd32
, senderQ
->msg32
,
442 senderQ
->wParam32
, senderQ
->lParam
);
444 else /* Win16 message */
445 result
= CallWindowProc16( (WNDPROC16
)wndPtr
->winproc
,
446 (HWND16
) senderQ
->hWnd32
,
447 (UINT16
) senderQ
->msg32
,
448 LOWORD (senderQ
->wParam32
),
451 queue
->GetMessageExtraInfoVal
= extraInfo
; /* Restore extra info */
452 TRACE(msg
,"\trcm: result = %08x\n", (unsigned)result
);
454 else WARN(msg
, "\trcm: bad hWnd\n");
456 QUEUE_Unlock( senderQ
);
458 /* Return the result to the sender task */
459 ReplyMessage16( result
);
461 queue
->InSendMessageHandle
= prevSender
;
462 queue
->smResultCurrent
= prevCtrlPtr
;
464 TRACE(msg
,"done!\n");
467 /***********************************************************************
470 * Try to reply to all pending sent messages on exit.
472 void QUEUE_FlushMessages( HQUEUE16 hQueue
)
474 MESSAGEQUEUE
*queue
= (MESSAGEQUEUE
*)QUEUE_Lock( hQueue
);
478 MESSAGEQUEUE
*senderQ
= (MESSAGEQUEUE
*)QUEUE_Lock( queue
->hSendingTask
);
479 QSMCTRL
* CtrlPtr
= queue
->smResultCurrent
;
481 TRACE(msg
,"Flushing queue %04x:\n", hQueue
);
486 CtrlPtr
= senderQ
->smResultInit
;
488 TRACE(msg
,"\tfrom queue %04x, smResult %08x\n", queue
->hSendingTask
, (unsigned)CtrlPtr
);
490 if( !(queue
->hSendingTask
= senderQ
->hPrevSendingTask
) )
491 QUEUE_ClearWakeBit( queue
, QS_SENDMESSAGE
);
493 QUEUE_SetWakeBit( senderQ
, QS_SMPARAMSFREE
);
495 queue
->smResultCurrent
= CtrlPtr
;
496 while( senderQ
->wakeBits
& QS_SMRESULT
) OldYield();
498 senderQ
->SendMessageReturn
= 0;
499 senderQ
->smResult
= queue
->smResultCurrent
;
500 QUEUE_SetWakeBit( senderQ
, QS_SMRESULT
);
502 QUEUE_Unlock( senderQ
);
504 senderQ
= (MESSAGEQUEUE
*)QUEUE_Lock( queue
->hSendingTask
);
507 queue
->InSendMessageHandle
= 0;
509 QUEUE_Unlock( queue
);
514 /***********************************************************************
517 * Add a message to the queue. Return FALSE if queue is full.
519 BOOL32
QUEUE_AddMsg( HQUEUE16 hQueue
, MSG32
*msg
, DWORD extraInfo
)
521 MESSAGEQUEUE
*msgQueue
;
525 if (!(msgQueue
= (MESSAGEQUEUE
*)QUEUE_Lock( hQueue
))) return FALSE
;
527 /* allocate new message in global heap for now */
528 if (!(qmsg
= (QMSG
*) HeapAlloc( SystemHeap
, 0, sizeof(QMSG
) ) ))
530 QUEUE_Unlock( msgQueue
);
534 EnterCriticalSection( &msgQueue
->cSection
);
538 qmsg
->extraInfo
= extraInfo
;
540 /* insert the message in the link list */
542 qmsg
->prevMsg
= msgQueue
->lastMsg
;
544 if (msgQueue
->lastMsg
)
545 msgQueue
->lastMsg
->nextMsg
= qmsg
;
547 /* update first and last anchor in message queue */
548 msgQueue
->lastMsg
= qmsg
;
549 if (!msgQueue
->firstMsg
)
550 msgQueue
->firstMsg
= qmsg
;
552 msgQueue
->msgCount
++;
554 LeaveCriticalSection( &msgQueue
->cSection
);
556 QUEUE_SetWakeBit( msgQueue
, QS_POSTMESSAGE
);
557 QUEUE_Unlock( msgQueue
);
564 /***********************************************************************
567 * Find a message matching the given parameters. Return -1 if none available.
569 QMSG
* QUEUE_FindMsg( MESSAGEQUEUE
* msgQueue
, HWND32 hwnd
, int first
, int last
)
573 EnterCriticalSection( &msgQueue
->cSection
);
575 if (!msgQueue
->msgCount
)
577 else if (!hwnd
&& !first
&& !last
)
578 qmsg
= msgQueue
->firstMsg
;
581 /* look in linked list for message matching first and last criteria */
582 for (qmsg
= msgQueue
->firstMsg
; qmsg
; qmsg
= qmsg
->nextMsg
)
584 MSG32
*msg
= &(qmsg
->msg
);
586 if (!hwnd
|| (msg
->hwnd
== hwnd
))
589 break; /* found it */
591 if ((msg
->message
>= first
) && (msg
->message
<= last
))
592 break; /* found it */
597 LeaveCriticalSection( &msgQueue
->cSection
);
604 /***********************************************************************
607 * Remove a message from the queue (pos must be a valid position).
609 void QUEUE_RemoveMsg( MESSAGEQUEUE
* msgQueue
, QMSG
*qmsg
)
611 EnterCriticalSection( &msgQueue
->cSection
);
613 /* set the linked list */
615 qmsg
->prevMsg
->nextMsg
= qmsg
->nextMsg
;
618 qmsg
->nextMsg
->prevMsg
= qmsg
->prevMsg
;
620 if (msgQueue
->firstMsg
== qmsg
)
621 msgQueue
->firstMsg
= qmsg
->nextMsg
;
623 if (msgQueue
->lastMsg
== qmsg
)
624 msgQueue
->lastMsg
= qmsg
->prevMsg
;
626 /* deallocate the memory for the message */
627 HeapFree( SystemHeap
, 0, qmsg
);
629 msgQueue
->msgCount
--;
630 if (!msgQueue
->msgCount
) msgQueue
->wakeBits
&= ~QS_POSTMESSAGE
;
632 LeaveCriticalSection( &msgQueue
->cSection
);
636 /***********************************************************************
639 * Wake a queue upon reception of a hardware event.
641 static void QUEUE_WakeSomeone( UINT32 message
)
647 MESSAGEQUEUE
*queue
= NULL
;
650 hQueue
= hCursorQueue
;
652 if( (message
>= WM_KEYFIRST
) && (message
<= WM_KEYLAST
) )
656 hQueue
= hActiveQueue
;
660 wakeBit
= (message
== WM_MOUSEMOVE
) ? QS_MOUSEMOVE
: QS_MOUSEBUTTON
;
661 if( (hwnd
= GetCapture32()) )
662 if( (wndPtr
= WIN_FindWndPtr( hwnd
)) )
664 hQueue
= wndPtr
->hmemTaskQ
;
668 if( (hwnd
= GetSysModalWindow16()) )
670 if( (wndPtr
= WIN_FindWndPtr( hwnd
)) )
671 hQueue
= wndPtr
->hmemTaskQ
;
675 queue
= QUEUE_Lock( hQueue
);
679 queue
= QUEUE_Lock( hFirstQueue
);
682 if (queue
->wakeMask
& wakeBit
) break;
685 queue
= QUEUE_Lock( queue
->next
);
689 WARN(msg
, "couldn't find queue\n");
694 QUEUE_SetWakeBit( queue
, wakeBit
);
696 QUEUE_Unlock( queue
);
700 /***********************************************************************
703 * Add an event to the system message queue.
704 * Note: the position is relative to the desktop window.
706 void hardware_event( WORD message
, WORD wParam
, LONG lParam
,
707 int xPos
, int yPos
, DWORD time
, DWORD extraInfo
)
710 QMSG
*qmsg
= sysMsgQueue
->lastMsg
;
713 if (!sysMsgQueue
) return;
715 /* Merge with previous event if possible */
717 if ((message
== WM_MOUSEMOVE
) && sysMsgQueue
->lastMsg
)
719 msg
= &(sysMsgQueue
->lastMsg
->msg
);
721 if ((msg
->message
== message
) && (msg
->wParam
== wParam
))
724 qmsg
= sysMsgQueue
->lastMsg
;
731 /* Should I limit the number of message in
732 the system message queue??? */
734 /* Don't merge allocate a new msg in the global heap */
736 if (!(qmsg
= (QMSG
*) HeapAlloc( SystemHeap
, 0, sizeof(QMSG
) ) ))
739 /* put message at the end of the linked list */
741 qmsg
->prevMsg
= sysMsgQueue
->lastMsg
;
743 if (sysMsgQueue
->lastMsg
)
744 sysMsgQueue
->lastMsg
->nextMsg
= qmsg
;
746 /* set last and first anchor index in system message queue */
747 sysMsgQueue
->lastMsg
= qmsg
;
748 if (!sysMsgQueue
->firstMsg
)
749 sysMsgQueue
->firstMsg
= qmsg
;
751 sysMsgQueue
->msgCount
++;
757 msg
->message
= message
;
758 msg
->wParam
= wParam
;
759 msg
->lParam
= lParam
;
763 qmsg
->extraInfo
= extraInfo
;
765 QUEUE_WakeSomeone( message
);
769 /***********************************************************************
772 HTASK16
QUEUE_GetQueueTask( HQUEUE16 hQueue
)
776 MESSAGEQUEUE
*queue
= QUEUE_Lock( hQueue
);
780 hTask
= queue
->thdb
->process
->task
;
781 QUEUE_Unlock( queue
);
789 /***********************************************************************
790 * QUEUE_IncPaintCount
792 void QUEUE_IncPaintCount( HQUEUE16 hQueue
)
796 if (!(queue
= (MESSAGEQUEUE
*)QUEUE_Lock( hQueue
))) return;
797 queue
->wPaintCount
++;
798 QUEUE_SetWakeBit( queue
, QS_PAINT
);
799 QUEUE_Unlock( queue
);
803 /***********************************************************************
804 * QUEUE_DecPaintCount
806 void QUEUE_DecPaintCount( HQUEUE16 hQueue
)
810 if (!(queue
= (MESSAGEQUEUE
*)QUEUE_Lock( hQueue
))) return;
811 queue
->wPaintCount
--;
812 if (!queue
->wPaintCount
) queue
->wakeBits
&= ~QS_PAINT
;
813 QUEUE_Unlock( queue
);
817 /***********************************************************************
818 * QUEUE_IncTimerCount
820 void QUEUE_IncTimerCount( HQUEUE16 hQueue
)
824 if (!(queue
= (MESSAGEQUEUE
*)QUEUE_Lock( hQueue
))) return;
825 queue
->wTimerCount
++;
826 QUEUE_SetWakeBit( queue
, QS_TIMER
);
827 QUEUE_Unlock( queue
);
831 /***********************************************************************
832 * QUEUE_DecTimerCount
834 void QUEUE_DecTimerCount( HQUEUE16 hQueue
)
838 if (!(queue
= (MESSAGEQUEUE
*)QUEUE_Lock( hQueue
))) return;
839 queue
->wTimerCount
--;
840 if (!queue
->wTimerCount
) queue
->wakeBits
&= ~QS_TIMER
;
841 QUEUE_Unlock( queue
);
845 /***********************************************************************
846 * PostQuitMessage16 (USER.6)
848 void WINAPI
PostQuitMessage16( INT16 exitCode
)
850 PostQuitMessage32( exitCode
);
854 /***********************************************************************
855 * PostQuitMessage32 (USER32.421)
857 * PostQuitMessage() posts a message to the system requesting an
858 * application to terminate execution. As a result of this function,
859 * the WM_QUIT message is posted to the application, and
860 * PostQuitMessage() returns immediately. The exitCode parameter
861 * specifies an application-defined exit code, which appears in the
862 * _wParam_ parameter of the WM_QUIT message posted to the application.
868 void WINAPI
PostQuitMessage32( INT32 exitCode
)
872 if (!(queue
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue() ))) return;
873 queue
->wPostQMsg
= TRUE
;
874 queue
->wExitCode
= (WORD
)exitCode
;
875 QUEUE_Unlock( queue
);
879 /***********************************************************************
880 * GetWindowTask16 (USER.224)
882 HTASK16 WINAPI
GetWindowTask16( HWND16 hwnd
)
884 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
886 if (!wndPtr
) return 0;
887 return QUEUE_GetQueueTask( wndPtr
->hmemTaskQ
);
890 /***********************************************************************
891 * GetWindowThreadProcessId (USER32.313)
893 DWORD WINAPI
GetWindowThreadProcessId( HWND32 hwnd
, LPDWORD process
)
898 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
900 if (!wndPtr
) return 0;
901 htask
=QUEUE_GetQueueTask( wndPtr
->hmemTaskQ
);
902 tdb
= (TDB
*)GlobalLock16(htask
);
903 if (!tdb
|| !tdb
->thdb
) return 0;
904 if (process
) *process
= PDB_TO_PROCESS_ID( tdb
->thdb
->process
);
905 return THDB_TO_THREAD_ID( tdb
->thdb
);
909 /***********************************************************************
910 * SetMessageQueue16 (USER.266)
912 BOOL16 WINAPI
SetMessageQueue16( INT16 size
)
914 return SetMessageQueue32( size
);
918 /***********************************************************************
919 * SetMessageQueue32 (USER32.494)
921 BOOL32 WINAPI
SetMessageQueue32( INT32 size
)
923 /* now obsolete the message queue will be expanded dynamically
926 /* access the queue to create it if it's not existing */
932 /***********************************************************************
933 * InitThreadInput (USER.409)
935 HQUEUE16 WINAPI
InitThreadInput( WORD unknown
, WORD flags
)
938 MESSAGEQUEUE
*queuePtr
;
940 THDB
*thdb
= THREAD_Current();
945 hQueue
= thdb
->teb
.queue
;
949 /* Create thread message queue */
950 if( !(hQueue
= QUEUE_CreateMsgQueue( 0 )))
952 WARN(msg
, "failed!\n");
956 /* Link new queue into list */
957 queuePtr
= (MESSAGEQUEUE
*)QUEUE_Lock( hQueue
);
958 queuePtr
->thdb
= THREAD_Current();
961 SetThreadQueue( 0, hQueue
);
962 thdb
->teb
.queue
= hQueue
;
964 queuePtr
->next
= hFirstQueue
;
965 hFirstQueue
= hQueue
;
968 QUEUE_Unlock( queuePtr
);
974 /***********************************************************************
975 * GetQueueStatus16 (USER.334)
977 DWORD WINAPI
GetQueueStatus16( UINT16 flags
)
982 if (!(queue
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue() ))) return 0;
983 ret
= MAKELONG( queue
->changeBits
, queue
->wakeBits
);
984 queue
->changeBits
= 0;
985 QUEUE_Unlock( queue
);
987 return ret
& MAKELONG( flags
, flags
);
990 /***********************************************************************
991 * GetQueueStatus32 (USER32.283)
993 DWORD WINAPI
GetQueueStatus32( UINT32 flags
)
998 if (!(queue
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue() ))) return 0;
999 ret
= MAKELONG( queue
->changeBits
, queue
->wakeBits
);
1000 queue
->changeBits
= 0;
1001 QUEUE_Unlock( queue
);
1003 return ret
& MAKELONG( flags
, flags
);
1007 /***********************************************************************
1008 * GetInputState16 (USER.335)
1010 BOOL16 WINAPI
GetInputState16(void)
1012 return GetInputState32();
1015 /***********************************************************************
1016 * WaitForInputIdle (USER32.577)
1018 DWORD WINAPI
WaitForInputIdle (HANDLE32 hProcess
, DWORD dwTimeOut
)
1020 FIXME (msg
, "(hProcess=%d, dwTimeOut=%ld): stub\n", hProcess
, dwTimeOut
);
1022 return WAIT_TIMEOUT
;
1026 /***********************************************************************
1027 * GetInputState32 (USER32.244)
1029 BOOL32 WINAPI
GetInputState32(void)
1031 MESSAGEQUEUE
*queue
;
1034 if (!(queue
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue() )))
1036 ret
= queue
->wakeBits
& (QS_KEY
| QS_MOUSEBUTTON
);
1037 QUEUE_Unlock( queue
);
1042 /***********************************************************************
1043 * UserYield (USER.332)
1045 void WINAPI
UserYield(void)
1047 TDB
*pCurTask
= (TDB
*)GlobalLock16( GetCurrentTask() );
1048 MESSAGEQUEUE
*queue
= (MESSAGEQUEUE
*)QUEUE_Lock( pCurTask
->hQueue
);
1050 if ( !THREAD_IsWin16( THREAD_Current() ) )
1052 FIXME(task
, "called for Win32 thread (%04x)!\n", THREAD_Current()->teb_sel
);
1053 QUEUE_Unlock( queue
);
1057 /* Handle sent messages */
1058 while (queue
&& (queue
->wakeBits
& QS_SENDMESSAGE
))
1059 QUEUE_ReceiveMessage( queue
);
1061 QUEUE_Unlock( queue
);
1065 queue
= (MESSAGEQUEUE
*)QUEUE_Lock( pCurTask
->hQueue
);
1066 while (queue
&& (queue
->wakeBits
& QS_SENDMESSAGE
))
1067 QUEUE_ReceiveMessage( queue
);
1069 QUEUE_Unlock( queue
);
1072 /***********************************************************************
1073 * GetMessagePos (USER.119) (USER32.272)
1075 * The GetMessagePos() function returns a long value representing a
1076 * cursor position, in screen coordinates, when the last message
1077 * retrieved by the GetMessage() function occurs. The x-coordinate is
1078 * in the low-order word of the return value, the y-coordinate is in
1079 * the high-order word. The application can use the MAKEPOINT()
1080 * macro to obtain a POINT structure from the return value.
1082 * For the current cursor position, use GetCursorPos().
1086 * Cursor position of last message on success, zero on failure.
1093 DWORD WINAPI
GetMessagePos(void)
1095 MESSAGEQUEUE
*queue
;
1098 if (!(queue
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue() ))) return 0;
1099 ret
= queue
->GetMessagePosVal
;
1100 QUEUE_Unlock( queue
);
1106 /***********************************************************************
1107 * GetMessageTime (USER.120) (USER32.273)
1109 * GetMessageTime() returns the message time for the last message
1110 * retrieved by the function. The time is measured in milliseconds with
1111 * the same offset as GetTickCount().
1113 * Since the tick count wraps, this is only useful for moderately short
1114 * relative time comparisons.
1118 * Time of last message on success, zero on failure.
1125 LONG WINAPI
GetMessageTime(void)
1127 MESSAGEQUEUE
*queue
;
1130 if (!(queue
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue() ))) return 0;
1131 ret
= queue
->GetMessageTimeVal
;
1132 QUEUE_Unlock( queue
);
1138 /***********************************************************************
1139 * GetMessageExtraInfo (USER.288) (USER32.271)
1141 LONG WINAPI
GetMessageExtraInfo(void)
1143 MESSAGEQUEUE
*queue
;
1146 if (!(queue
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue() ))) return 0;
1147 ret
= queue
->GetMessageExtraInfoVal
;
1148 QUEUE_Unlock( queue
);