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 MESSAGEQUEUE
*pCursorQueue
= NULL
;
32 MESSAGEQUEUE
*pActiveQueue
= NULL
;
34 /***********************************************************************
37 void QUEUE_DumpQueue( HQUEUE16 hQueue
)
41 if (!(pq
= (MESSAGEQUEUE
*) GlobalLock16( hQueue
)) ||
42 GlobalSize16(hQueue
) < sizeof(MESSAGEQUEUE
)+pq
->queueSize
*sizeof(QMSG
))
44 WARN(msg
, "%04x is not a queue handle\n", hQueue
);
48 DUMP( "next: %12.4x Intertask SendMessage:\n"
49 "hTask: %11.4x ----------------------\n"
50 "msgSize: %9.4x hWnd: %10.4x\n"
51 "msgCount: %8.4x msg: %11.4x\n"
52 "msgNext: %9.4x wParam: %8.4x\n"
53 "msgFree: %9.4x lParam: %8.8x\n"
54 "qSize: %11.4x lRet: %10.8x\n"
55 "wWinVer: %9.4x ISMH: %10.4x\n"
56 "paints: %10.4x hSendTask: %5.4x\n"
57 "timers: %10.4x hPrevSend: %5.4x\n"
61 pq
->next
, pq
->hTask
, pq
->msgSize
, pq
->hWnd
,
62 pq
->msgCount
, pq
->msg
, pq
->nextMessage
, pq
->wParam
,
63 pq
->nextFreeMessage
, (unsigned)pq
->lParam
, pq
->queueSize
,
64 (unsigned)pq
->SendMessageReturn
, pq
->wWinVersion
, pq
->InSendMessageHandle
,
65 pq
->wPaintCount
, pq
->hSendingTask
, pq
->wTimerCount
,
66 pq
->hPrevSendingTask
, pq
->wakeBits
, pq
->wakeMask
, pq
->hCurHook
);
70 /***********************************************************************
73 void QUEUE_WalkQueues(void)
76 HQUEUE16 hQueue
= hFirstQueue
;
78 DUMP( "Queue Size Msgs Task\n" );
81 MESSAGEQUEUE
*queue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
);
84 WARN( msg
, "Bad queue handle %04x\n", hQueue
);
87 if (!GetModuleName( queue
->hTask
, module
, sizeof(module
)))
88 strcpy( module
, "???" );
89 DUMP( "%04x %5d %4d %04x %s\n", hQueue
, queue
->msgSize
,
90 queue
->msgCount
, queue
->hTask
, module
);
97 /***********************************************************************
98 * QUEUE_IsExitingQueue
100 BOOL32
QUEUE_IsExitingQueue( HQUEUE16 hQueue
)
102 return (hExitingQueue
&& (hQueue
== hExitingQueue
));
106 /***********************************************************************
107 * QUEUE_SetExitingQueue
109 void QUEUE_SetExitingQueue( HQUEUE16 hQueue
)
111 hExitingQueue
= hQueue
;
115 /***********************************************************************
116 * QUEUE_CreateMsgQueue
118 * Creates a message queue. Doesn't link it into queue list!
120 static HQUEUE16
QUEUE_CreateMsgQueue( int size
)
123 MESSAGEQUEUE
* msgQueue
;
125 TDB
*pTask
= (TDB
*)GlobalLock16( GetCurrentTask() );
127 TRACE(msg
,"Creating message queue...\n");
129 queueSize
= sizeof(MESSAGEQUEUE
) + size
* sizeof(QMSG
);
130 if (!(hQueue
= GlobalAlloc16( GMEM_FIXED
| GMEM_ZEROINIT
, queueSize
)))
132 msgQueue
= (MESSAGEQUEUE
*) GlobalLock16( hQueue
);
133 msgQueue
->self
= hQueue
;
134 msgQueue
->msgSize
= sizeof(QMSG
);
135 msgQueue
->queueSize
= size
;
136 msgQueue
->wakeBits
= msgQueue
->changeBits
= QS_SMPARAMSFREE
;
137 msgQueue
->wWinVersion
= pTask
? pTask
->version
: 0;
138 GlobalUnlock16( hQueue
);
143 /***********************************************************************
144 * QUEUE_DeleteMsgQueue
146 * Unlinks and deletes a message queue.
148 * Note: We need to mask asynchronous events to make sure PostMessage works
149 * even in the signal handler.
151 BOOL32
QUEUE_DeleteMsgQueue( HQUEUE16 hQueue
)
153 MESSAGEQUEUE
* msgQueue
= (MESSAGEQUEUE
*)GlobalLock16(hQueue
);
157 TRACE(msg
,"Deleting message queue %04x\n", hQueue
);
159 if (!hQueue
|| !msgQueue
)
161 WARN(msg
, "invalid argument.\n");
164 if( pCursorQueue
== msgQueue
) pCursorQueue
= NULL
;
165 if( pActiveQueue
== msgQueue
) pActiveQueue
= NULL
;
167 /* flush sent messages */
168 senderQ
= msgQueue
->hSendingTask
;
171 MESSAGEQUEUE
* sq
= (MESSAGEQUEUE
*)GlobalLock16(senderQ
);
173 sq
->SendMessageReturn
= 0L;
174 QUEUE_SetWakeBit( sq
, QS_SMRESULT
);
175 senderQ
= sq
->hPrevSendingTask
;
178 SIGNAL_MaskAsyncEvents( TRUE
);
180 pPrev
= &hFirstQueue
;
181 while (*pPrev
&& (*pPrev
!= hQueue
))
183 MESSAGEQUEUE
*msgQ
= (MESSAGEQUEUE
*)GlobalLock16(*pPrev
);
186 if (*pPrev
) *pPrev
= msgQueue
->next
;
189 SIGNAL_MaskAsyncEvents( FALSE
);
191 GlobalFree16( hQueue
);
196 /***********************************************************************
197 * QUEUE_CreateSysMsgQueue
199 * Create the system message queue, and set the double-click speed.
200 * Must be called only once.
202 BOOL32
QUEUE_CreateSysMsgQueue( int size
)
204 if (size
> MAX_QUEUE_SIZE
) size
= MAX_QUEUE_SIZE
;
205 else if (size
<= 0) size
= 1;
206 if (!(hmemSysMsgQueue
= QUEUE_CreateMsgQueue( size
))) return FALSE
;
207 sysMsgQueue
= (MESSAGEQUEUE
*) GlobalLock16( hmemSysMsgQueue
);
212 /***********************************************************************
215 MESSAGEQUEUE
*QUEUE_GetSysQueue(void)
220 /***********************************************************************
223 void QUEUE_Signal( HTASK16 hTask
)
229 TDB
*pTask
= (TDB
*)GlobalLock16( hTask
);
230 if ( !pTask
) return;
232 TRACE(msg
, "calling SYNC_MsgWakeUp\n");
234 /* Wake up thread waiting for message */
235 /* NOTE: This should really wake up *the* thread that owns
236 the queue. Since we dont't have thread-local message
237 queues yet, we wake up all waiting threads ... */
239 /* FIXME: should be replaced by a server event */
241 pdb
= pTask
->thdb
->process
;
242 entry
= pdb
? pdb
->thread_list
->next
: NULL
;
247 if (entry
->thread
->wait_struct
.wait_msg
)
249 SYNC_MsgWakeUp( entry
->thread
);
252 if (entry
== pdb
->thread_list
) break;
262 /***********************************************************************
265 void QUEUE_Wait( void )
267 if ( THREAD_IsWin16( THREAD_Current() ) )
271 TRACE(msg
, "current task is 32-bit, calling SYNC_DoWait\n");
272 SYNC_DoWait( 0, NULL
, FALSE
, INFINITE32
, FALSE
, TRUE
);
277 /***********************************************************************
280 * See "Windows Internals", p.449
282 void QUEUE_SetWakeBit( MESSAGEQUEUE
*queue
, WORD bit
)
284 TRACE(msg
,"queue = %04x (wm=%04x), bit = %04x\n",
285 queue
->self
, queue
->wakeMask
, bit
);
287 if (bit
& QS_MOUSE
) pMouseQueue
= queue
;
288 if (bit
& QS_KEY
) pKbdQueue
= queue
;
289 queue
->changeBits
|= bit
;
290 queue
->wakeBits
|= bit
;
291 if (queue
->wakeMask
& bit
)
294 QUEUE_Signal( queue
->hTask
);
299 /***********************************************************************
302 void QUEUE_ClearWakeBit( MESSAGEQUEUE
*queue
, WORD bit
)
304 queue
->changeBits
&= ~bit
;
305 queue
->wakeBits
&= ~bit
;
309 /***********************************************************************
312 * See "Windows Internals", p.447
314 void QUEUE_WaitBits( WORD bits
)
318 TRACE(msg
,"q %04x waiting for %04x\n", GetFastQueue(), bits
);
322 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetFastQueue() ))) return;
324 if (queue
->changeBits
& bits
)
326 /* One of the bits is set; we can return */
330 if (queue
->wakeBits
& QS_SENDMESSAGE
)
332 /* Process the sent message immediately */
335 QUEUE_ReceiveMessage( queue
);
336 continue; /* nested sm crux */
339 queue
->wakeMask
= bits
| QS_SENDMESSAGE
;
340 if(queue
->changeBits
& bits
) continue;
342 TRACE(msg
,"%04x) wakeMask is %04x, waiting\n", queue
->self
, queue
->wakeMask
);
349 /***********************************************************************
350 * QUEUE_ReceiveMessage
352 * This routine is called when a sent message is waiting for the queue.
354 void QUEUE_ReceiveMessage( MESSAGEQUEUE
*queue
)
356 MESSAGEQUEUE
*senderQ
= NULL
;
357 HQUEUE16 prevSender
= 0;
358 QSMCTRL
* prevCtrlPtr
= NULL
;
361 TRACE(msg
, "ReceiveMessage, queue %04x\n", queue
->self
);
362 if (!(queue
->wakeBits
& QS_SENDMESSAGE
) ||
363 !(senderQ
= (MESSAGEQUEUE
*)GlobalLock16( queue
->hSendingTask
)))
364 { TRACE(msg
,"\trcm: nothing to do\n"); return; }
366 if( !senderQ
->hPrevSendingTask
)
367 QUEUE_ClearWakeBit( queue
, QS_SENDMESSAGE
); /* no more sent messages */
369 /* Save current state on stack */
370 prevSender
= queue
->InSendMessageHandle
;
371 prevCtrlPtr
= queue
->smResultCurrent
;
373 /* Remove sending queue from the list */
374 queue
->InSendMessageHandle
= queue
->hSendingTask
;
375 queue
->smResultCurrent
= senderQ
->smResultInit
;
376 queue
->hSendingTask
= senderQ
->hPrevSendingTask
;
378 TRACE(msg
, "\trcm: smResultCurrent = %08x, prevCtrl = %08x\n",
379 (unsigned)queue
->smResultCurrent
, (unsigned)prevCtrlPtr
);
380 QUEUE_SetWakeBit( senderQ
, QS_SMPARAMSFREE
);
382 TRACE(msg
, "\trcm: calling wndproc - %04x %04x %04x%04x %08x\n",
383 senderQ
->hWnd
, senderQ
->msg
, senderQ
->wParamHigh
,
384 senderQ
->wParam
, (unsigned)senderQ
->lParam
);
386 if (IsWindow32( senderQ
->hWnd
))
388 WND
*wndPtr
= WIN_FindWndPtr( senderQ
->hWnd
);
389 DWORD extraInfo
= queue
->GetMessageExtraInfoVal
;
390 queue
->GetMessageExtraInfoVal
= senderQ
->GetMessageExtraInfoVal
;
392 if (senderQ
->flags
& QUEUE_SM_WIN32
)
394 WPARAM32 wParam
= MAKELONG( senderQ
->wParam
, senderQ
->wParamHigh
);
395 TRACE(msg
, "\trcm: msg is Win32\n" );
396 if (senderQ
->flags
& QUEUE_SM_UNICODE
)
397 result
= CallWindowProc32W( wndPtr
->winproc
,
398 senderQ
->hWnd
, senderQ
->msg
,
399 wParam
, senderQ
->lParam
);
401 result
= CallWindowProc32A( wndPtr
->winproc
,
402 senderQ
->hWnd
, senderQ
->msg
,
403 wParam
, senderQ
->lParam
);
405 else /* Win16 message */
406 result
= CallWindowProc16( (WNDPROC16
)wndPtr
->winproc
,
407 senderQ
->hWnd
, senderQ
->msg
,
408 senderQ
->wParam
, senderQ
->lParam
);
410 queue
->GetMessageExtraInfoVal
= extraInfo
; /* Restore extra info */
411 TRACE(msg
,"\trcm: result = %08x\n", (unsigned)result
);
413 else WARN(msg
, "\trcm: bad hWnd\n");
415 /* Return the result to the sender task */
416 ReplyMessage16( result
);
418 queue
->InSendMessageHandle
= prevSender
;
419 queue
->smResultCurrent
= prevCtrlPtr
;
421 TRACE(msg
,"done!\n");
424 /***********************************************************************
427 * Try to reply to all pending sent messages on exit.
429 void QUEUE_FlushMessages( HQUEUE16 hQueue
)
431 MESSAGEQUEUE
*queue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
);
435 MESSAGEQUEUE
*senderQ
= (MESSAGEQUEUE
*)GlobalLock16( queue
->hSendingTask
);
436 QSMCTRL
* CtrlPtr
= queue
->smResultCurrent
;
438 TRACE(msg
,"Flushing queue %04x:\n", hQueue
);
443 CtrlPtr
= senderQ
->smResultInit
;
445 TRACE(msg
,"\tfrom queue %04x, smResult %08x\n", queue
->hSendingTask
, (unsigned)CtrlPtr
);
447 if( !(queue
->hSendingTask
= senderQ
->hPrevSendingTask
) )
448 QUEUE_ClearWakeBit( queue
, QS_SENDMESSAGE
);
450 QUEUE_SetWakeBit( senderQ
, QS_SMPARAMSFREE
);
452 queue
->smResultCurrent
= CtrlPtr
;
453 while( senderQ
->wakeBits
& QS_SMRESULT
) OldYield();
455 senderQ
->SendMessageReturn
= 0;
456 senderQ
->smResult
= queue
->smResultCurrent
;
457 QUEUE_SetWakeBit( senderQ
, QS_SMRESULT
);
459 senderQ
= (MESSAGEQUEUE
*)GlobalLock16( queue
->hSendingTask
);
462 queue
->InSendMessageHandle
= 0;
466 /***********************************************************************
469 * Add a message to the queue. Return FALSE if queue is full.
471 BOOL32
QUEUE_AddMsg( HQUEUE16 hQueue
, MSG16
* msg
, DWORD extraInfo
)
474 MESSAGEQUEUE
*msgQueue
;
476 SIGNAL_MaskAsyncEvents( TRUE
);
478 if (!(msgQueue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
))) return FALSE
;
479 pos
= msgQueue
->nextFreeMessage
;
481 /* Check if queue is full */
482 if ((pos
== msgQueue
->nextMessage
) && (msgQueue
->msgCount
> 0))
484 SIGNAL_MaskAsyncEvents( FALSE
);
485 WARN( msg
,"Queue is full!\n" );
490 msgQueue
->messages
[pos
].msg
= *msg
;
491 msgQueue
->messages
[pos
].extraInfo
= extraInfo
;
492 if (pos
< msgQueue
->queueSize
-1) pos
++;
494 msgQueue
->nextFreeMessage
= pos
;
495 msgQueue
->msgCount
++;
497 SIGNAL_MaskAsyncEvents( FALSE
);
499 QUEUE_SetWakeBit( msgQueue
, QS_POSTMESSAGE
);
504 /***********************************************************************
507 * Find a message matching the given parameters. Return -1 if none available.
509 int QUEUE_FindMsg( MESSAGEQUEUE
* msgQueue
, HWND32 hwnd
, int first
, int last
)
511 int i
, pos
= msgQueue
->nextMessage
;
513 TRACE(msg
,"hwnd=%04x pos=%d\n", hwnd
, pos
);
515 if (!msgQueue
->msgCount
) return -1;
516 if (!hwnd
&& !first
&& !last
) return pos
;
518 for (i
= 0; i
< msgQueue
->msgCount
; i
++)
520 MSG16
* msg
= &msgQueue
->messages
[pos
].msg
;
522 if (!hwnd
|| (msg
->hwnd
== hwnd
))
524 if (!first
&& !last
) return pos
;
525 if ((msg
->message
>= first
) && (msg
->message
<= last
)) return pos
;
527 if (pos
< msgQueue
->queueSize
-1) pos
++;
534 /***********************************************************************
537 * Remove a message from the queue (pos must be a valid position).
539 void QUEUE_RemoveMsg( MESSAGEQUEUE
* msgQueue
, int pos
)
541 SIGNAL_MaskAsyncEvents( TRUE
);
543 if (pos
>= msgQueue
->nextMessage
)
545 for ( ; pos
> msgQueue
->nextMessage
; pos
--)
546 msgQueue
->messages
[pos
] = msgQueue
->messages
[pos
-1];
547 msgQueue
->nextMessage
++;
548 if (msgQueue
->nextMessage
>= msgQueue
->queueSize
)
549 msgQueue
->nextMessage
= 0;
553 for ( ; pos
< msgQueue
->nextFreeMessage
; pos
++)
554 msgQueue
->messages
[pos
] = msgQueue
->messages
[pos
+1];
555 if (msgQueue
->nextFreeMessage
) msgQueue
->nextFreeMessage
--;
556 else msgQueue
->nextFreeMessage
= msgQueue
->queueSize
-1;
558 msgQueue
->msgCount
--;
559 if (!msgQueue
->msgCount
) msgQueue
->wakeBits
&= ~QS_POSTMESSAGE
;
561 SIGNAL_MaskAsyncEvents( FALSE
);
565 /***********************************************************************
568 * Wake a queue upon reception of a hardware event.
570 static void QUEUE_WakeSomeone( UINT32 message
)
575 MESSAGEQUEUE
*queue
= pCursorQueue
;
577 if( (message
>= WM_KEYFIRST
) && (message
<= WM_KEYLAST
) )
580 if( pActiveQueue
) queue
= pActiveQueue
;
584 wakeBit
= (message
== WM_MOUSEMOVE
) ? QS_MOUSEMOVE
: QS_MOUSEBUTTON
;
585 if( (hwnd
= GetCapture32()) )
586 if( (wndPtr
= WIN_FindWndPtr( hwnd
)) )
587 queue
= (MESSAGEQUEUE
*)GlobalLock16( wndPtr
->hmemTaskQ
);
590 if( (hwnd
= GetSysModalWindow16()) )
591 if( (wndPtr
= WIN_FindWndPtr( hwnd
)) )
592 queue
= (MESSAGEQUEUE
*)GlobalLock16( wndPtr
->hmemTaskQ
);
596 queue
= GlobalLock16( hFirstQueue
);
599 if (queue
->wakeMask
& wakeBit
) break;
600 queue
= GlobalLock16( queue
->next
);
604 WARN(msg
, "couldn't find queue\n");
609 QUEUE_SetWakeBit( queue
, wakeBit
);
613 /***********************************************************************
616 * Add an event to the system message queue.
617 * Note: the position is relative to the desktop window.
619 void hardware_event( WORD message
, WORD wParam
, LONG lParam
,
620 int xPos
, int yPos
, DWORD time
, DWORD extraInfo
)
625 if (!sysMsgQueue
) return;
626 pos
= sysMsgQueue
->nextFreeMessage
;
628 /* Merge with previous event if possible */
630 if ((message
== WM_MOUSEMOVE
) && sysMsgQueue
->msgCount
)
633 else pos
= sysMsgQueue
->queueSize
- 1;
634 msg
= &sysMsgQueue
->messages
[pos
].msg
;
635 if ((msg
->message
== message
) && (msg
->wParam
== wParam
))
636 sysMsgQueue
->msgCount
--; /* Merge events */
638 pos
= sysMsgQueue
->nextFreeMessage
; /* Don't merge */
641 /* Check if queue is full */
643 if ((pos
== sysMsgQueue
->nextMessage
) && sysMsgQueue
->msgCount
)
645 /* Queue is full, beep (but not on every mouse motion...) */
646 if (message
!= WM_MOUSEMOVE
) MessageBeep32(0);
652 msg
= &sysMsgQueue
->messages
[pos
].msg
;
654 msg
->message
= message
;
655 msg
->wParam
= wParam
;
656 msg
->lParam
= lParam
;
658 msg
->pt
.x
= xPos
& 0xffff;
659 msg
->pt
.y
= yPos
& 0xffff;
660 sysMsgQueue
->messages
[pos
].extraInfo
= extraInfo
;
661 if (pos
< sysMsgQueue
->queueSize
- 1) pos
++;
663 sysMsgQueue
->nextFreeMessage
= pos
;
664 sysMsgQueue
->msgCount
++;
665 QUEUE_WakeSomeone( message
);
669 /***********************************************************************
672 HTASK16
QUEUE_GetQueueTask( HQUEUE16 hQueue
)
674 MESSAGEQUEUE
*queue
= GlobalLock16( hQueue
);
675 return (queue
) ? queue
->hTask
: 0 ;
679 /***********************************************************************
680 * QUEUE_IncPaintCount
682 void QUEUE_IncPaintCount( HQUEUE16 hQueue
)
686 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
))) return;
687 queue
->wPaintCount
++;
688 QUEUE_SetWakeBit( queue
, QS_PAINT
);
692 /***********************************************************************
693 * QUEUE_DecPaintCount
695 void QUEUE_DecPaintCount( HQUEUE16 hQueue
)
699 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
))) return;
700 queue
->wPaintCount
--;
701 if (!queue
->wPaintCount
) queue
->wakeBits
&= ~QS_PAINT
;
705 /***********************************************************************
706 * QUEUE_IncTimerCount
708 void QUEUE_IncTimerCount( HQUEUE16 hQueue
)
712 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
))) return;
713 queue
->wTimerCount
++;
714 QUEUE_SetWakeBit( queue
, QS_TIMER
);
718 /***********************************************************************
719 * QUEUE_DecTimerCount
721 void QUEUE_DecTimerCount( HQUEUE16 hQueue
)
725 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
))) return;
726 queue
->wTimerCount
--;
727 if (!queue
->wTimerCount
) queue
->wakeBits
&= ~QS_TIMER
;
731 /***********************************************************************
732 * PostQuitMessage16 (USER.6)
734 void WINAPI
PostQuitMessage16( INT16 exitCode
)
736 PostQuitMessage32( exitCode
);
740 /***********************************************************************
741 * PostQuitMessage32 (USER32.421)
743 * PostQuitMessage() posts a message to the system requesting an
744 * application to terminate execution. As a result of this function,
745 * the WM_QUIT message is posted to the application, and
746 * PostQuitMessage() returns immediately. The exitCode parameter
747 * specifies an application-defined exit code, which appears in the
748 * _wParam_ parameter of the WM_QUIT message posted to the application.
754 void WINAPI
PostQuitMessage32( INT32 exitCode
)
758 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetFastQueue() ))) return;
759 queue
->wPostQMsg
= TRUE
;
760 queue
->wExitCode
= (WORD
)exitCode
;
764 /***********************************************************************
765 * GetWindowTask16 (USER.224)
767 HTASK16 WINAPI
GetWindowTask16( HWND16 hwnd
)
769 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
771 if (!wndPtr
) return 0;
772 return QUEUE_GetQueueTask( wndPtr
->hmemTaskQ
);
775 /***********************************************************************
776 * GetWindowThreadProcessId (USER32.313)
778 DWORD WINAPI
GetWindowThreadProcessId( HWND32 hwnd
, LPDWORD process
)
783 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
785 if (!wndPtr
) return 0;
786 htask
=QUEUE_GetQueueTask( wndPtr
->hmemTaskQ
);
787 tdb
= (TDB
*)GlobalLock16(htask
);
788 if (!tdb
|| !tdb
->thdb
) return 0;
789 if (process
) *process
= PDB_TO_PROCESS_ID( tdb
->thdb
->process
);
790 return THDB_TO_THREAD_ID( tdb
->thdb
);
794 /***********************************************************************
795 * SetMessageQueue16 (USER.266)
797 BOOL16 WINAPI
SetMessageQueue16( INT16 size
)
799 return SetMessageQueue32( size
);
803 /***********************************************************************
804 * SetMessageQueue32 (USER32.494)
806 BOOL32 WINAPI
SetMessageQueue32( INT32 size
)
808 HQUEUE16 hQueue
, hNewQueue
;
809 MESSAGEQUEUE
*queuePtr
;
811 TRACE(msg
,"task %04x size %i\n", GetCurrentTask(), size
);
813 if ((size
> MAX_QUEUE_SIZE
) || (size
<= 0)) return FALSE
;
815 if( !(hNewQueue
= QUEUE_CreateMsgQueue( size
)))
817 WARN(msg
, "failed!\n");
820 queuePtr
= (MESSAGEQUEUE
*)GlobalLock16( hNewQueue
);
822 SIGNAL_MaskAsyncEvents( TRUE
);
824 /* Copy data and free the old message queue */
825 if ((hQueue
= GetThreadQueue(0)) != 0)
827 MESSAGEQUEUE
*oldQ
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
);
828 memcpy( &queuePtr
->wParamHigh
, &oldQ
->wParamHigh
,
829 (int)oldQ
->messages
- (int)(&oldQ
->wParamHigh
) );
830 HOOK_ResetQueueHooks( hNewQueue
);
831 if( WIN_GetDesktop()->hmemTaskQ
== hQueue
)
832 WIN_GetDesktop()->hmemTaskQ
= hNewQueue
;
833 WIN_ResetQueueWindows( WIN_GetDesktop(), hQueue
, hNewQueue
);
834 CLIPBOARD_ResetLock( hQueue
, hNewQueue
);
835 QUEUE_DeleteMsgQueue( hQueue
);
838 /* Link new queue into list */
839 queuePtr
->hTask
= GetCurrentTask();
840 queuePtr
->next
= hFirstQueue
;
841 hFirstQueue
= hNewQueue
;
843 if( !queuePtr
->next
) pCursorQueue
= queuePtr
;
844 SetThreadQueue( 0, hNewQueue
);
846 SIGNAL_MaskAsyncEvents( FALSE
);
850 /***********************************************************************
851 * InitThreadInput (USER.409)
853 HQUEUE16 WINAPI
InitThreadInput( WORD unknown
, WORD flags
)
855 HQUEUE16 hQueue
= GetTaskQueue( 0 );
857 FIXME( msg
, "(%04X,%04X): should create thread-local message queue!\n",
860 SetFastQueue( 0, hQueue
);
864 /***********************************************************************
865 * GetQueueStatus16 (USER.334)
867 DWORD WINAPI
GetQueueStatus16( UINT16 flags
)
872 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetFastQueue() ))) return 0;
873 ret
= MAKELONG( queue
->changeBits
, queue
->wakeBits
);
874 queue
->changeBits
= 0;
875 return ret
& MAKELONG( flags
, flags
);
878 /***********************************************************************
879 * GetQueueStatus32 (USER32.283)
881 DWORD WINAPI
GetQueueStatus32( UINT32 flags
)
886 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetFastQueue() ))) return 0;
887 ret
= MAKELONG( queue
->changeBits
, queue
->wakeBits
);
888 queue
->changeBits
= 0;
889 return ret
& MAKELONG( flags
, flags
);
893 /***********************************************************************
894 * GetInputState16 (USER.335)
896 BOOL16 WINAPI
GetInputState16(void)
898 return GetInputState32();
901 /***********************************************************************
902 * WaitForInputIdle (USER32.577)
904 DWORD WINAPI
WaitForInputIdle (HANDLE32 hProcess
, DWORD dwTimeOut
)
906 FIXME (msg
, "(hProcess=%d, dwTimeOut=%ld): stub\n", hProcess
, dwTimeOut
);
912 /***********************************************************************
913 * GetInputState32 (USER32.244)
915 BOOL32 WINAPI
GetInputState32(void)
919 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetFastQueue() )))
921 return queue
->wakeBits
& (QS_KEY
| QS_MOUSEBUTTON
);
924 /***********************************************************************
925 * UserYield (USER.332)
927 void WINAPI
UserYield(void)
929 TDB
*pCurTask
= (TDB
*)GlobalLock16( GetCurrentTask() );
930 MESSAGEQUEUE
*queue
= (MESSAGEQUEUE
*)GlobalLock16( pCurTask
->hQueue
);
932 if ( !THREAD_IsWin16( THREAD_Current() ) )
934 FIXME(task
, "called for Win32 thread (%04x)!\n", THREAD_Current()->teb_sel
);
938 /* Handle sent messages */
939 while (queue
&& (queue
->wakeBits
& QS_SENDMESSAGE
))
940 QUEUE_ReceiveMessage( queue
);
944 queue
= (MESSAGEQUEUE
*)GlobalLock16( pCurTask
->hQueue
);
945 while (queue
&& (queue
->wakeBits
& QS_SENDMESSAGE
))
946 QUEUE_ReceiveMessage( queue
);
949 /***********************************************************************
950 * GetMessagePos (USER.119) (USER32.272)
952 * The GetMessagePos() function returns a long value representing a
953 * cursor position, in screen coordinates, when the last message
954 * retrieved by the GetMessage() function occurs. The x-coordinate is
955 * in the low-order word of the return value, the y-coordinate is in
956 * the high-order word. The application can use the MAKEPOINT()
957 * macro to obtain a POINT structure from the return value.
959 * For the current cursor position, use GetCursorPos().
963 * Cursor position of last message on success, zero on failure.
970 DWORD WINAPI
GetMessagePos(void)
974 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetFastQueue() ))) return 0;
975 return queue
->GetMessagePosVal
;
979 /***********************************************************************
980 * GetMessageTime (USER.120) (USER32.273)
982 * GetMessageTime() returns the message time for the last message
983 * retrieved by the function. The time is measured in milliseconds with
984 * the same offset as GetTickCount().
986 * Since the tick count wraps, this is only useful for moderately short
987 * relative time comparisons.
991 * Time of last message on success, zero on failure.
998 LONG WINAPI
GetMessageTime(void)
1000 MESSAGEQUEUE
*queue
;
1002 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetFastQueue() ))) return 0;
1003 return queue
->GetMessageTimeVal
;
1007 /***********************************************************************
1008 * GetMessageExtraInfo (USER.288) (USER32.271)
1010 LONG WINAPI
GetMessageExtraInfo(void)
1012 MESSAGEQUEUE
*queue
;
1014 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetFastQueue() ))) return 0;
1015 return queue
->GetMessageExtraInfoVal
;