2 * Message queues related functions
4 * Copyright 1993, 1994 Alexandre Julliard
11 #include <sys/types.h>
17 #include "sysmetrics.h"
33 #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
34 #define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
37 typedef enum { SYSQ_MSG_ABANDON, SYSQ_MSG_SKIP,
38 SYSQ_MSG_ACCEPT, SYSQ_MSG_CONTINUE } SYSQ_STATUS;
40 extern HQUEUE16 hCursorQueue; /* queue.c */
42 DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
44 static UINT32 doubleClickSpeed = 452;
45 static INT32 debugSMRL = 0; /* intertask SendMessage() recursion level */
47 /***********************************************************************
50 BOOL32 MSG_CheckFilter(DWORD uMsg, DWORD first, DWORD last)
53 return (uMsg >= first && uMsg <= last);
57 /***********************************************************************
58 * MSG_SendParentNotify
60 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
61 * the window has the WS_EX_NOPARENTNOTIFY style.
63 static void MSG_SendParentNotify(WND* wndPtr, WORD event, WORD idChild, LPARAM lValue)
65 #define lppt ((LPPOINT16)&lValue)
67 /* pt has to be in the client coordinates of the parent window */
69 MapWindowPoints16( 0, wndPtr->hwndSelf, lppt, 1 );
72 if (!(wndPtr->dwStyle & WS_CHILD) || (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY)) break;
73 lppt->x += wndPtr->rectClient.left;
74 lppt->y += wndPtr->rectClient.top;
75 wndPtr = wndPtr->parent;
76 SendMessage32A( wndPtr->hwndSelf, WM_PARENTNOTIFY,
77 MAKEWPARAM( event, idChild ), lValue );
83 /***********************************************************************
84 * MSG_TranslateMouseMsg
86 * Translate an mouse hardware event into a real mouse message.
87 * Return value indicates whether the translated message must be passed
88 * to the user, left in the queue, or skipped entirely (in this case
89 * HIWORD contains hit test code).
91 static DWORD MSG_TranslateMouseMsg( HWND32 hTopWnd, DWORD first, DWORD last,
92 MSG32 *msg, BOOL32 remove, WND* pWndScope )
94 static DWORD dblclk_time_limit = 0;
95 static UINT16 clk_message = 0;
96 static HWND16 clk_hwnd = 0;
97 static POINT16 clk_pos = { 0, 0 };
101 INT16 ht, hittest, sendSC = 0;
102 UINT32 message = msg->message;
103 POINT16 screen_pt, pt;
104 HANDLE16 hQ = GetFastQueue();
105 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock(hQ);
106 BOOL32 eatMsg = FALSE;
107 BOOL32 mouseClick = ((message == WM_LBUTTONDOWN) ||
108 (message == WM_RBUTTONDOWN) ||
109 (message == WM_MBUTTONDOWN))?1:0;
112 /* Find the window */
114 CONV_POINT32TO16( &msg->pt, &pt );
116 ht = hittest = HTCLIENT;
117 hWnd = GetCapture32();
120 ht = hittest = WINPOS_WindowFromPoint( pWndScope, pt, &pWnd );
121 if( !pWnd ) pWnd = WIN_GetDesktop();
122 hWnd = pWnd->hwndSelf;
127 pWnd = WIN_FindWndPtr(hWnd);
129 ht = PERQDATA_GetCaptureInfo( queue->pQData );
132 /* stop if not the right queue */
134 if (pWnd->hmemTaskQ != hQ)
136 /* Not for the current task */
137 if (queue) QUEUE_ClearWakeBit( queue, QS_MOUSE );
138 /* Wake up the other task */
139 QUEUE_Unlock( queue );
140 queue = (MESSAGEQUEUE *)QUEUE_Lock( pWnd->hmemTaskQ );
141 if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE );
143 QUEUE_Unlock( queue );
144 return SYSQ_MSG_ABANDON;
147 /* check if hWnd is within hWndScope */
149 if( hTopWnd && hWnd != hTopWnd )
150 if( !IsChild32(hTopWnd, hWnd) )
152 QUEUE_Unlock( queue );
153 return SYSQ_MSG_CONTINUE;
158 /* translate double clicks -
159 * note that ...MOUSEMOVEs can slip in between
160 * ...BUTTONDOWN and ...BUTTONDBLCLK messages */
162 if( pWnd->class->style & CS_DBLCLKS || ht != HTCLIENT )
164 if ((message == clk_message) && (hWnd == clk_hwnd) &&
165 (msg->time - dblclk_time_limit < doubleClickSpeed) &&
166 (abs(msg->pt.x - clk_pos.x) < SYSMETRICS_CXDOUBLECLK/2) &&
167 (abs(msg->pt.y - clk_pos.y) < SYSMETRICS_CYDOUBLECLK/2))
169 message += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN);
170 mouseClick++; /* == 2 */
176 if (hittest != HTCLIENT)
178 message += WM_NCMOUSEMOVE - WM_MOUSEMOVE;
179 msg->wParam = hittest;
181 else ScreenToClient16( hWnd, &pt );
183 /* check message filter */
185 if (!MSG_CheckFilter(message, first, last))
188 return SYSQ_MSG_CONTINUE;
191 hCursorQueue = queue->self;
196 if (HOOK_IsHooked( WH_MOUSE ))
198 MOUSEHOOKSTRUCT16 *hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16);
201 hook->pt = screen_pt;
203 hook->wHitTestCode = hittest;
204 hook->dwExtraInfo = 0;
205 ret = HOOK_CallHooks16( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
206 message, (LPARAM)SEGPTR_GET(hook) );
209 if( ret ) return MAKELONG((INT16)SYSQ_MSG_SKIP, hittest);
212 if ((hittest == HTERROR) || (hittest == HTNOWHERE))
214 else if( remove && mouseClick )
216 HWND32 hwndTop = WIN_GetTopParent( hWnd );
218 if( mouseClick == 1 )
221 dblclk_time_limit = msg->time;
222 clk_message = msg->message;
226 /* got double click - zero them out */
227 dblclk_time_limit = clk_hwnd = 0;
231 /* Send the WM_PARENTNOTIFY,
232 * note that even for double/nonclient clicks
233 * notification message is still WM_L/M/RBUTTONDOWN.
236 MSG_SendParentNotify( pWnd, msg->message & 0xffff, 0, MAKELPARAM(screen_pt.x, screen_pt.y) );
238 /* Activate the window if needed */
240 if (hWnd != GetActiveWindow32() && hWnd != GetDesktopWindow32())
242 LONG ret = SendMessage32A( hWnd, WM_MOUSEACTIVATE, hwndTop,
243 MAKELONG( hittest, message ) );
245 if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
248 if (((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT))
249 && hwndTop != GetActiveWindow32() )
250 if (!WINPOS_SetActiveWindow( hwndTop, TRUE , TRUE ))
254 } else sendSC = (remove && sendSC);
256 /* Send the WM_SETCURSOR message */
259 SendMessage32A( hWnd, WM_SETCURSOR, hWnd,
260 MAKELONG( hittest, message ));
261 if (eatMsg) return MAKELONG( (UINT16)SYSQ_MSG_SKIP, hittest);
264 msg->message = message;
265 msg->lParam = MAKELONG( pt.x, pt.y );
266 return SYSQ_MSG_ACCEPT;
270 /***********************************************************************
271 * MSG_TranslateKbdMsg
273 * Translate an keyboard hardware event into a real message.
275 static DWORD MSG_TranslateKbdMsg( HWND32 hTopWnd, DWORD first, DWORD last,
276 MSG32 *msg, BOOL32 remove )
278 WORD message = msg->message;
279 HWND32 hWnd = GetFocus32();
282 /* Should check Ctrl-Esc and PrintScreen here */
286 /* Send the message to the active window instead, */
287 /* translating messages to their WM_SYS equivalent */
289 hWnd = GetActiveWindow32();
291 if( message < WM_SYSKEYDOWN )
292 message += WM_SYSKEYDOWN - WM_KEYDOWN;
294 pWnd = WIN_FindWndPtr( hWnd );
295 if (pWnd && (pWnd->hmemTaskQ != GetFastQueue()))
297 /* Not for the current task */
298 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue() );
299 if (queue) QUEUE_ClearWakeBit( queue, QS_KEY );
300 QUEUE_Unlock( queue );
302 /* Wake up the other task */
303 queue = (MESSAGEQUEUE *)QUEUE_Lock( pWnd->hmemTaskQ );
304 if (queue) QUEUE_SetWakeBit( queue, QS_KEY );
305 QUEUE_Unlock( queue );
306 return SYSQ_MSG_ABANDON;
309 if (hTopWnd && hWnd != hTopWnd)
310 if (!IsChild32(hTopWnd, hWnd)) return SYSQ_MSG_CONTINUE;
311 if (!MSG_CheckFilter(message, first, last)) return SYSQ_MSG_CONTINUE;
314 msg->message = message;
316 return (HOOK_CallHooks16( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
317 LOWORD (msg->wParam), msg->lParam )
318 ? SYSQ_MSG_SKIP : SYSQ_MSG_ACCEPT);
322 /***********************************************************************
323 * MSG_JournalRecordMsg
325 * Build an EVENTMSG structure and call JOURNALRECORD hook
327 static void MSG_JournalRecordMsg( MSG32 *msg )
329 EVENTMSG32 *event = (EVENTMSG32 *) HeapAlloc(SystemHeap, 0, sizeof(EVENTMSG32));
331 event->message = msg->message;
332 event->time = msg->time;
333 if ((msg->message >= WM_KEYFIRST) && (msg->message <= WM_KEYLAST))
335 event->paramL = (msg->wParam & 0xFF) | (HIWORD(msg->lParam) << 8);
336 event->paramH = msg->lParam & 0x7FFF;
337 if (HIWORD(msg->lParam) & 0x0100)
338 event->paramH |= 0x8000; /* special_key - bit */
339 HOOK_CallHooks32A( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)event );
341 else if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST))
343 event->paramL = LOWORD(msg->lParam); /* X pos */
344 event->paramH = HIWORD(msg->lParam); /* Y pos */
345 ClientToScreen16( msg->hwnd, (LPPOINT16)&event->paramL );
346 HOOK_CallHooks32A( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)event );
348 else if ((msg->message >= WM_NCMOUSEFIRST) &&
349 (msg->message <= WM_NCMOUSELAST))
351 event->paramL = LOWORD(msg->lParam); /* X pos */
352 event->paramH = HIWORD(msg->lParam); /* Y pos */
353 event->message += WM_MOUSEMOVE-WM_NCMOUSEMOVE;/* give no info about NC area */
354 HOOK_CallHooks32A( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)event );
357 HeapFree(SystemHeap, 0, event);
360 /***********************************************************************
361 * MSG_JournalPlayBackMsg
363 * Get an EVENTMSG struct via call JOURNALPLAYBACK hook function
365 static int MSG_JournalPlayBackMsg(void)
368 long wtime,lParam,wParam;
369 WORD keyDown,i,result=0;
371 if ( HOOK_IsHooked( WH_JOURNALPLAYBACK ) )
373 tmpMsg = (EVENTMSG32 *) HeapAlloc(SystemHeap, 0, sizeof(EVENTMSG32));
374 if (!tmpMsg) return result;
376 wtime=HOOK_CallHooks32A( WH_JOURNALPLAYBACK, HC_GETNEXT, 0,
378 /* TRACE(msg,"Playback wait time =%ld\n",wtime); */
382 if ((tmpMsg->message>= WM_KEYFIRST) && (tmpMsg->message <= WM_KEYLAST))
384 wParam=tmpMsg->paramL & 0xFF;
385 lParam=MAKELONG(tmpMsg->paramH&0x7ffff,tmpMsg->paramL>>8);
386 if (tmpMsg->message == WM_KEYDOWN || tmpMsg->message == WM_SYSKEYDOWN)
388 for (keyDown=i=0; i<256 && !keyDown; i++)
389 if (InputKeyStateTable[i] & 0x80)
392 lParam |= 0x40000000;
393 AsyncKeyStateTable[wParam]=InputKeyStateTable[wParam] |= 0x80;
395 else /* WM_KEYUP, WM_SYSKEYUP */
397 lParam |= 0xC0000000;
398 AsyncKeyStateTable[wParam]=InputKeyStateTable[wParam] &= ~0x80;
400 if (InputKeyStateTable[VK_MENU] & 0x80)
401 lParam |= 0x20000000;
402 if (tmpMsg->paramH & 0x8000) /*special_key bit*/
403 lParam |= 0x01000000;
404 hardware_event( tmpMsg->message & 0xffff, LOWORD(wParam), lParam,
405 0, 0, tmpMsg->time, 0 );
409 if ((tmpMsg->message>= WM_MOUSEFIRST) && (tmpMsg->message <= WM_MOUSELAST))
411 switch (tmpMsg->message)
414 MouseButtonsStates[0]=AsyncMouseButtonsStates[0]=TRUE;break;
416 MouseButtonsStates[0]=AsyncMouseButtonsStates[0]=FALSE;break;
418 MouseButtonsStates[1]=AsyncMouseButtonsStates[1]=TRUE;break;
420 MouseButtonsStates[1]=AsyncMouseButtonsStates[1]=FALSE;break;
422 MouseButtonsStates[2]=AsyncMouseButtonsStates[2]=TRUE;break;
424 MouseButtonsStates[2]=AsyncMouseButtonsStates[2]=FALSE;break;
426 AsyncKeyStateTable[VK_LBUTTON]= InputKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0;
427 AsyncKeyStateTable[VK_MBUTTON]= InputKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
428 AsyncKeyStateTable[VK_RBUTTON]= InputKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
429 SetCursorPos32(tmpMsg->paramL,tmpMsg->paramH);
430 lParam=MAKELONG(tmpMsg->paramL,tmpMsg->paramH);
432 if (MouseButtonsStates[0]) wParam |= MK_LBUTTON;
433 if (MouseButtonsStates[1]) wParam |= MK_MBUTTON;
434 if (MouseButtonsStates[2]) wParam |= MK_RBUTTON;
435 hardware_event( tmpMsg->message & 0xffff, LOWORD (wParam), lParam,
436 tmpMsg->paramL, tmpMsg->paramH, tmpMsg->time, 0 );
439 HOOK_CallHooks32A( WH_JOURNALPLAYBACK, HC_SKIP, 0,
445 if( tmpMsg->message == WM_QUEUESYNC )
446 if (HOOK_IsHooked( WH_CBT ))
447 HOOK_CallHooks32A( WH_CBT, HCBT_QS, 0, 0L);
449 result= QS_MOUSE | QS_KEY; /* ? */
451 HeapFree(SystemHeap, 0, tmpMsg);
456 /***********************************************************************
457 * MSG_PeekHardwareMsg
459 * Peek for a hardware message matching the hwnd and message filters.
461 static BOOL32 MSG_PeekHardwareMsg( MSG32 *msg, HWND32 hwnd, DWORD first, DWORD last,
464 /* FIXME: should deal with MSG32 instead of MSG16 */
466 DWORD status = SYSQ_MSG_ACCEPT;
467 MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
469 QMSG *nextqmsg, *qmsg = sysMsgQueue->firstMsg;
471 /* FIXME: there has to be a better way to do this */
474 /* If the queue is empty, attempt to fill it */
475 if (!sysMsgQueue->msgCount && THREAD_IsWin16( THREAD_Current() )
477 EVENT_WaitNetEvent( FALSE, FALSE );
479 for ( kbd_msg = 0; qmsg; qmsg = nextqmsg)
484 nextqmsg = qmsg->nextMsg;
486 /* Translate message */
488 if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST))
490 HWND32 hWndScope = (HWND32)qmsg->extraInfo;
492 status = MSG_TranslateMouseMsg(hwnd, first, last, msg, remove,
493 (Options.managed && IsWindow32(hWndScope) )
494 ? WIN_FindWndPtr(hWndScope) : WIN_GetDesktop() );
497 else if ((msg->message >= WM_KEYFIRST) && (msg->message <= WM_KEYLAST))
499 status = MSG_TranslateKbdMsg(hwnd, first, last, msg, remove);
502 else /* Non-standard hardware event */
504 HARDWAREHOOKSTRUCT16 *hook;
505 if ((hook = SEGPTR_NEW(HARDWAREHOOKSTRUCT16)))
508 hook->hWnd = msg->hwnd;
509 hook->wMessage = msg->message & 0xffff;
510 hook->wParam = LOWORD (msg->wParam);
511 hook->lParam = msg->lParam;
512 ret = HOOK_CallHooks16( WH_HARDWARE,
513 remove ? HC_ACTION : HC_NOREMOVE,
514 0, (LPARAM)SEGPTR_GET(hook) );
518 QUEUE_RemoveMsg( sysMsgQueue, qmsg );
521 status = SYSQ_MSG_ACCEPT;
525 switch (LOWORD(status))
527 case SYSQ_MSG_ACCEPT:
531 if (HOOK_IsHooked( WH_CBT ))
534 HOOK_CallHooks16( WH_CBT, HCBT_KEYSKIPPED,
535 LOWORD (msg->wParam), msg->lParam );
538 MOUSEHOOKSTRUCT16 *hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16);
541 CONV_POINT32TO16( &msg->pt,&hook->pt );
542 hook->hwnd = msg->hwnd;
543 hook->wHitTestCode = HIWORD(status);
544 hook->dwExtraInfo = 0;
545 HOOK_CallHooks16( WH_CBT, HCBT_CLICKSKIPPED ,msg->message & 0xffff,
546 (LPARAM)SEGPTR_GET(hook) );
553 QUEUE_RemoveMsg( sysMsgQueue, qmsg );
556 case SYSQ_MSG_CONTINUE:
559 case SYSQ_MSG_ABANDON:
565 if (HOOK_IsHooked( WH_JOURNALRECORD )) MSG_JournalRecordMsg( msg );
566 QUEUE_RemoveMsg( sysMsgQueue, qmsg );
574 /**********************************************************************
575 * SetDoubleClickTime16 (USER.20)
577 void WINAPI SetDoubleClickTime16( UINT16 interval )
579 SetDoubleClickTime32( interval );
583 /**********************************************************************
584 * SetDoubleClickTime32 (USER32.480)
586 BOOL32 WINAPI SetDoubleClickTime32( UINT32 interval )
588 doubleClickSpeed = interval ? interval : 500;
593 /**********************************************************************
594 * GetDoubleClickTime16 (USER.21)
596 UINT16 WINAPI GetDoubleClickTime16(void)
598 return doubleClickSpeed;
602 /**********************************************************************
603 * GetDoubleClickTime32 (USER32.239)
605 UINT32 WINAPI GetDoubleClickTime32(void)
607 return doubleClickSpeed;
611 /***********************************************************************
614 * Implementation of an inter-task SendMessage.
616 static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND16 hwnd, UINT16 msg,
617 WPARAM32 wParam, LPARAM lParam, WORD flags )
619 INT32 prevSMRL = debugSMRL;
620 QSMCTRL qCtrl = { 0, 1};
621 MESSAGEQUEUE *queue, *destQ;
623 if (IsTaskLocked() || !IsWindow32(hwnd))
626 if (!(queue = (MESSAGEQUEUE*)QUEUE_Lock( GetFastQueue() ))) return 0;
628 if (!(destQ = (MESSAGEQUEUE*)QUEUE_Lock( hDestQueue )))
630 QUEUE_Unlock( queue );
635 TRACE(sendmsg,"%*sSM: %s [%04x] (%04x -> %04x)\n",
636 prevSMRL, "", SPY_GetMsgName(msg), msg, queue->self, hDestQueue );
638 if( !(queue->wakeBits & QS_SMPARAMSFREE) )
640 TRACE(sendmsg,"\tIntertask SendMessage: sleeping since unreplied SendMessage pending\n");
641 QUEUE_WaitBits( QS_SMPARAMSFREE );
645 queue->hWnd32 = hwnd;
647 queue->wParam32 = wParam;
648 queue->lParam = lParam;
649 queue->hPrevSendingTask = destQ->hSendingTask;
650 destQ->hSendingTask = GetFastQueue();
652 QUEUE_ClearWakeBit( queue, QS_SMPARAMSFREE );
653 queue->flags = (queue->flags & ~(QUEUE_SM_WIN32|QUEUE_SM_UNICODE)) | flags;
655 TRACE(sendmsg,"%*ssm: smResultInit = %08x\n", prevSMRL, "", (unsigned)&qCtrl);
657 queue->smResultInit = &qCtrl;
659 QUEUE_SetWakeBit( destQ, QS_SENDMESSAGE );
661 /* perform task switch and wait for the result */
663 while( qCtrl.bPending )
665 if (!(queue->wakeBits & QS_SMRESULT))
667 if (THREAD_IsWin16( THREAD_Current() ))
668 DirectedYield( destQ->thdb->teb.htask16 );
669 QUEUE_WaitBits( QS_SMRESULT );
670 TRACE(sendmsg,"\tsm: have result!\n");
674 TRACE(sendmsg,"%*ssm: smResult = %08x\n", prevSMRL, "", (unsigned)queue->smResult );
676 if (queue->smResult) { /* FIXME, smResult should always be set */
677 queue->smResult->lResult = queue->SendMessageReturn;
678 queue->smResult->bPending = FALSE;
680 QUEUE_ClearWakeBit( queue, QS_SMRESULT );
682 if( queue->smResult != &qCtrl )
683 ERR(sendmsg, "%*ssm: weird scenes inside the goldmine!\n", prevSMRL, "");
685 queue->smResultInit = NULL;
687 TRACE(sendmsg,"%*sSM: [%04x] returning %08lx\n", prevSMRL, "", msg, qCtrl.lResult);
690 QUEUE_Unlock( queue );
691 QUEUE_Unlock( destQ );
693 return qCtrl.lResult;
697 /***********************************************************************
698 * ReplyMessage16 (USER.115)
700 void WINAPI ReplyMessage16( LRESULT result )
702 MESSAGEQUEUE *senderQ;
705 if (!(queue = (MESSAGEQUEUE*)QUEUE_Lock( GetFastQueue() ))) return;
707 TRACE(msg,"ReplyMessage, queue %04x\n", queue->self);
709 while( (senderQ = (MESSAGEQUEUE*)QUEUE_Lock( queue->InSendMessageHandle)))
711 TRACE(msg,"\trpm: replying to %08x (%04x -> %04x)\n",
712 queue->msg32, queue->self, senderQ->self);
714 if( queue->wakeBits & QS_SENDMESSAGE )
716 QUEUE_ReceiveMessage( queue );
717 QUEUE_Unlock( senderQ );
718 continue; /* ReceiveMessage() already called us */
721 if(!(senderQ->wakeBits & QS_SMRESULT) ) break;
722 if (THREAD_IsWin16(THREAD_Current())) OldYield();
724 QUEUE_Unlock( senderQ );
728 TRACE(msg,"\trpm: done\n");
729 QUEUE_Unlock( queue );
733 senderQ->SendMessageReturn = result;
734 TRACE(msg,"\trpm: smResult = %08x, result = %08lx\n",
735 (unsigned)queue->smResultCurrent, result );
737 senderQ->smResult = queue->smResultCurrent;
738 queue->InSendMessageHandle = 0;
740 QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
741 if (THREAD_IsWin16( THREAD_Current() ))
742 DirectedYield( senderQ->thdb->teb.htask16 );
744 QUEUE_Unlock( senderQ );
745 QUEUE_Unlock( queue );
749 /***********************************************************************
752 static BOOL32 MSG_PeekMessage( LPMSG32 msg, HWND32 hwnd, DWORD first, DWORD last,
753 WORD flags, BOOL32 peek )
756 MESSAGEQUEUE *msgQueue;
761 DDE_TestDDE(hwnd); /* do we have dde handling in the window ?*/
762 DDE_GetRemoteMessage();
763 #endif /* CONFIG_IPC */
765 mask = QS_POSTMESSAGE | QS_SENDMESSAGE; /* Always selected */
768 if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
769 if ( ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) ||
770 ((first <= WM_NCMOUSELAST) && (last >= WM_NCMOUSEFIRST)) ) mask |= QS_MOUSE;
771 if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= QS_TIMER;
772 if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= QS_TIMER;
773 if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= QS_PAINT;
775 else mask |= QS_MOUSE | QS_KEY | QS_TIMER | QS_PAINT;
777 if (IsTaskLocked()) flags |= PM_NOYIELD;
779 /* Never yield on Win32 threads */
780 if (!THREAD_IsWin16(THREAD_Current())) flags |= PM_NOYIELD;
786 hQueue = GetFastQueue();
787 msgQueue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
788 if (!msgQueue) return FALSE;
789 msgQueue->changeBits = 0;
791 /* First handle a message put by SendMessage() */
793 while (msgQueue->wakeBits & QS_SENDMESSAGE)
794 QUEUE_ReceiveMessage( msgQueue );
796 /* Now handle a WM_QUIT message */
798 if (msgQueue->wPostQMsg &&
799 (!first || WM_QUIT >= first) &&
800 (!last || WM_QUIT <= last) )
803 msg->message = WM_QUIT;
804 msg->wParam = msgQueue->wExitCode;
806 if (flags & PM_REMOVE) msgQueue->wPostQMsg = 0;
810 /* Now find a normal message */
812 if (((msgQueue->wakeBits & mask) & QS_POSTMESSAGE) &&
813 ((qmsg = QUEUE_FindMsg( msgQueue, hwnd, first, last )) != 0))
817 msgQueue->GetMessageTimeVal = msg->time;
818 CONV_POINT32TO16(&msg->pt, &pt16);
819 msgQueue->GetMessagePosVal = *(DWORD *)&pt16;
820 msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
822 if (flags & PM_REMOVE) QUEUE_RemoveMsg( msgQueue, qmsg );
826 msgQueue->changeBits |= MSG_JournalPlayBackMsg();
828 /* Now find a hardware event */
830 if (((msgQueue->wakeBits & mask) & (QS_MOUSE | QS_KEY)) &&
831 MSG_PeekHardwareMsg( msg, hwnd, first, last, flags & PM_REMOVE ))
834 msgQueue->GetMessageTimeVal = msg->time;
835 CONV_POINT32TO16(&msg->pt, &pt16);
836 msgQueue->GetMessagePosVal = *(DWORD *)&pt16;
837 msgQueue->GetMessageExtraInfoVal = 0; /* Always 0 for now */
841 /* Check again for SendMessage */
843 while (msgQueue->wakeBits & QS_SENDMESSAGE)
844 QUEUE_ReceiveMessage( msgQueue );
846 /* Now find a WM_PAINT message */
848 if ((msgQueue->wakeBits & mask) & QS_PAINT)
851 msg->hwnd = WIN_FindWinToRepaint( hwnd , hQueue );
852 msg->message = WM_PAINT;
856 if ((wndPtr = WIN_FindWndPtr(msg->hwnd)))
858 if( wndPtr->dwStyle & WS_MINIMIZE &&
859 wndPtr->class->hIcon )
861 msg->message = WM_PAINTICON;
865 if( !hwnd || msg->hwnd == hwnd || IsChild16(hwnd,msg->hwnd) )
867 if( wndPtr->flags & WIN_INTERNAL_PAINT && !wndPtr->hrgnUpdate)
869 wndPtr->flags &= ~WIN_INTERNAL_PAINT;
870 QUEUE_DecPaintCount( hQueue );
877 /* Check for timer messages, but yield first */
879 if (!(flags & PM_NOYIELD))
882 while (msgQueue->wakeBits & QS_SENDMESSAGE)
883 QUEUE_ReceiveMessage( msgQueue );
885 if ((msgQueue->wakeBits & mask) & QS_TIMER)
887 if (TIMER_GetTimerMsg(msg, hwnd, hQueue, flags & PM_REMOVE)) break;
892 if (!(flags & PM_NOYIELD)) UserYield();
894 QUEUE_Unlock( msgQueue );
897 msgQueue->wakeMask = mask;
898 QUEUE_WaitBits( mask );
899 QUEUE_Unlock( msgQueue );
902 /* instead of unlocking queue for every break condition, all break
903 condition will fall here */
904 QUEUE_Unlock( msgQueue );
906 /* We got a message */
907 if (flags & PM_REMOVE)
909 WORD message = msg->message;
911 if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
913 BYTE *p = &QueueKeyStateTable[msg->wParam & 0xff];
919 else if (message == WM_KEYUP || message == WM_SYSKEYUP)
920 QueueKeyStateTable[msg->wParam & 0xff] &= ~0x80;
922 if (peek) return TRUE;
923 else return (msg->message != WM_QUIT);
926 /***********************************************************************
927 * MSG_InternalGetMessage
929 * GetMessage() function for internal use. Behave like GetMessage(),
930 * but also call message filters and optionally send WM_ENTERIDLE messages.
931 * 'hwnd' must be the handle of the dialog or menu window.
932 * 'code' is the message filter value (MSGF_??? codes).
934 BOOL32 MSG_InternalGetMessage( MSG32 *msg, HWND32 hwnd, HWND32 hwndOwner,
935 WPARAM32 code, WORD flags, BOOL32 sendIdle )
941 if (!MSG_PeekMessage( msg, 0, 0, 0, flags, TRUE ))
943 /* No message present -> send ENTERIDLE and wait */
944 if (IsWindow32(hwndOwner))
945 SendMessage32A( hwndOwner, WM_ENTERIDLE,
946 code, (LPARAM)hwnd );
947 MSG_PeekMessage( msg, 0, 0, 0, flags, FALSE );
950 else /* Always wait for a message */
951 MSG_PeekMessage( msg, 0, 0, 0, flags, FALSE );
953 /* Call message filters */
955 if (HOOK_IsHooked( WH_SYSMSGFILTER ) || HOOK_IsHooked( WH_MSGFILTER ))
957 MSG32 *pmsg = HeapAlloc( SystemHeap, 0, sizeof(MSG32) );
962 ret = (HOOK_CallHooks32A( WH_SYSMSGFILTER, code, 0,
964 HOOK_CallHooks32A( WH_MSGFILTER, code, 0,
967 HeapFree( SystemHeap, 0, pmsg );
970 /* Message filtered -> remove it from the queue */
971 /* if it's still there. */
972 if (!(flags & PM_REMOVE))
973 MSG_PeekMessage( msg, 0, 0, 0, PM_REMOVE, TRUE );
979 return (msg->message != WM_QUIT);
984 /***********************************************************************
985 * PeekMessage16 (USER.109)
987 BOOL16 WINAPI PeekMessage16( LPMSG16 lpmsg, HWND16 hwnd, UINT16 first,
988 UINT16 last, UINT16 flags )
992 ret = PeekMessage32A(&msg32, hwnd, first, last, flags);
993 STRUCT32_MSG32to16(&msg32, lpmsg);
997 /***********************************************************************
998 * WIN16_PeekMessage32 (USER.819)
1000 BOOL16 WINAPI WIN16_PeekMessage32( LPMSG16_32 lpmsg16_32, HWND16 hwnd,
1001 UINT16 first, UINT16 last, UINT16 flags, BOOL16 wHaveParamHigh )
1003 if (wHaveParamHigh == FALSE)
1005 lpmsg16_32->wParamHigh = 0;
1006 return PeekMessage16(&(lpmsg16_32->msg), hwnd, first, last, flags);
1013 ret = (BOOL16)PeekMessage32A(&msg32, (HWND32)hwnd,
1014 (UINT32)first, (UINT32)last, (UINT32)flags);
1015 lpmsg16_32->msg.hwnd = msg32.hwnd;
1016 lpmsg16_32->msg.message = msg32.message;
1017 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
1018 lpmsg16_32->msg.lParam = msg32.lParam;
1019 lpmsg16_32->msg.time = msg32.time;
1020 lpmsg16_32->msg.pt.x = (INT16)msg32.pt.x;
1021 lpmsg16_32->msg.pt.y = (INT16)msg32.pt.y;
1022 lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
1028 /***********************************************************************
1031 BOOL32 WINAPI PeekMessage32A( LPMSG32 lpmsg, HWND32 hwnd,
1032 UINT32 min,UINT32 max,UINT32 wRemoveMsg)
1034 return MSG_PeekMessage( lpmsg, hwnd, min, max, wRemoveMsg, TRUE );
1037 /***********************************************************************
1038 * PeekMessageW Check queue for messages
1040 * Checks for a message in the thread's queue, filtered as for
1041 * GetMessage(). Returns immediately whether a message is available
1044 * Whether a retrieved message is removed from the queue is set by the
1045 * _wRemoveMsg_ flags, which should be one of the following values:
1047 * PM_NOREMOVE Do not remove the message from the queue.
1049 * PM_REMOVE Remove the message from the queue.
1051 * In addition, PM_NOYIELD may be combined into _wRemoveMsg_ to
1052 * request that the system not yield control during PeekMessage();
1053 * however applications may not rely on scheduling behavior.
1057 * Nonzero if a message is available and is retrieved, zero otherwise.
1064 BOOL32 WINAPI PeekMessage32W(
1065 LPMSG32 lpmsg, /* buffer to receive message */
1066 HWND32 hwnd, /* restrict to messages for hwnd */
1067 UINT32 min, /* minimum message to receive */
1068 UINT32 max, /* maximum message to receive */
1069 UINT32 wRemoveMsg /* removal flags */
1071 /* FIXME: Should perform Unicode translation on specific messages */
1072 return PeekMessage32A(lpmsg,hwnd,min,max,wRemoveMsg);
1075 /***********************************************************************
1076 * GetMessage16 (USER.108)
1078 BOOL16 WINAPI GetMessage16( SEGPTR msg, HWND16 hwnd, UINT16 first, UINT16 last)
1081 MSG16 *lpmsg = (MSG16 *)PTR_SEG_TO_LIN(msg);
1084 ret = GetMessage32A( &msg32, hwnd, first, last );
1086 STRUCT32_MSG32to16( &msg32, lpmsg );
1088 TRACE(msg,"message %04x, hwnd %04x, filter(%04x - %04x)\n", lpmsg->message,
1089 hwnd, first, last );
1094 /***********************************************************************
1095 * WIN16_GetMessage32 (USER.820)
1097 BOOL16 WINAPI WIN16_GetMessage32( SEGPTR msg16_32, HWND16 hWnd, UINT16 first,
1098 UINT16 last, BOOL16 wHaveParamHigh )
1100 MSG16_32 *lpmsg16_32 = (MSG16_32 *)PTR_SEG_TO_LIN(msg16_32);
1102 if (wHaveParamHigh == FALSE) /* normal GetMessage16 call */
1105 lpmsg16_32->wParamHigh = 0; /* you never know... */
1106 /* WARNING: msg16_32->msg has to be the first variable in the struct */
1107 return GetMessage16(msg16_32, hWnd, first, last);
1114 ret = (BOOL16)GetMessage32A(&msg32, hWnd, first, last);
1115 lpmsg16_32->msg.hwnd = msg32.hwnd;
1116 lpmsg16_32->msg.message = msg32.message;
1117 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
1118 lpmsg16_32->msg.lParam = msg32.lParam;
1119 lpmsg16_32->msg.time = msg32.time;
1120 lpmsg16_32->msg.pt.x = (INT16)msg32.pt.x;
1121 lpmsg16_32->msg.pt.y = (INT16)msg32.pt.y;
1122 lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
1127 /***********************************************************************
1128 * GetMessage32A (USER32.270)
1130 BOOL32 WINAPI GetMessage32A(MSG32* lpmsg,HWND32 hwnd,UINT32 min,UINT32 max)
1132 MSG_PeekMessage( lpmsg, hwnd, min, max, PM_REMOVE, FALSE );
1134 TRACE(msg,"message %04x, hwnd %04x, filter(%04x - %04x)\n", lpmsg->message,
1137 HOOK_CallHooks32A( WH_GETMESSAGE, HC_ACTION, 0, (LPARAM)lpmsg );
1139 return (lpmsg->message != WM_QUIT);
1142 /***********************************************************************
1143 * GetMessage32W (USER32.274) Retrieve next message
1145 * GetMessage retrieves the next event from the calling thread's
1146 * queue and deposits it in *lpmsg.
1148 * If _hwnd_ is not NULL, only messages for window _hwnd_ and its
1149 * children as specified by IsChild() are retrieved. If _hwnd_ is NULL
1150 * all application messages are retrieved.
1152 * _min_ and _max_ specify the range of messages of interest. If
1153 * min==max==0, no filtering is performed. Useful examples are
1154 * WM_KEYFIRST and WM_KEYLAST to retrieve keyboard input, and
1155 * WM_MOUSEFIRST and WM_MOUSELAST to retrieve mouse input.
1157 * WM_PAINT messages are not removed from the queue; they remain until
1158 * processed. Other messages are removed from the queue.
1162 * -1 on error, 0 if message is WM_QUIT, nonzero otherwise.
1169 BOOL32 WINAPI GetMessage32W(
1170 MSG32* lpmsg, /* buffer to receive message */
1171 HWND32 hwnd, /* restrict to messages for hwnd */
1172 UINT32 min, /* minimum message to receive */
1173 UINT32 max /* maximum message to receive */
1176 return GetMessage32A(lpmsg, hwnd, min, max);
1180 /***********************************************************************
1181 * PostMessage16 (USER.110)
1183 BOOL16 WINAPI PostMessage16( HWND16 hwnd, UINT16 message, WPARAM16 wParam,
1186 return (BOOL16) PostMessage32A( hwnd, message, wParam, lParam );
1190 /***********************************************************************
1191 * PostMessage32A (USER32.419)
1193 BOOL32 WINAPI PostMessage32A( HWND32 hwnd, UINT32 message, WPARAM32 wParam,
1200 msg.message = message;
1201 msg.wParam = wParam;
1202 msg.lParam = lParam;
1203 msg.time = GetTickCount();
1208 if (DDE_PostMessage(&msg))
1210 #endif /* CONFIG_IPC */
1212 if (hwnd == HWND_BROADCAST)
1214 TRACE(msg,"HWND_BROADCAST !\n");
1215 for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next)
1217 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
1219 TRACE(msg,"BROADCAST Message to hWnd=%04x m=%04X w=%04X l=%08lX !\n",
1220 wndPtr->hwndSelf, message, wParam, lParam);
1221 PostMessage32A( wndPtr->hwndSelf, message, wParam, lParam );
1224 TRACE(msg,"End of HWND_BROADCAST !\n");
1228 wndPtr = WIN_FindWndPtr( hwnd );
1229 if (!wndPtr || !wndPtr->hmemTaskQ) return FALSE;
1231 return QUEUE_AddMsg( wndPtr->hmemTaskQ, &msg, 0 );
1235 /***********************************************************************
1236 * PostMessage32W (USER32.420)
1238 BOOL32 WINAPI PostMessage32W( HWND32 hwnd, UINT32 message, WPARAM32 wParam,
1242 return PostMessage32A( hwnd, message, wParam, lParam );
1246 /***********************************************************************
1247 * PostAppMessage16 (USER.116)
1249 BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 message, WPARAM16 wParam,
1254 if (GetTaskQueue(hTask) == 0) return FALSE;
1256 msg.message = message;
1257 msg.wParam = wParam;
1258 msg.lParam = lParam;
1259 msg.time = GetTickCount();
1263 return QUEUE_AddMsg( GetTaskQueue(hTask), &msg, 0 );
1267 /***********************************************************************
1268 * SendMessage16 (USER.111)
1270 LRESULT WINAPI SendMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
1274 WND **list, **ppWnd;
1278 MSG16 DDE_msg = { hwnd, msg, wParam, lParam };
1279 if (DDE_SendMessage(&DDE_msg)) return TRUE;
1280 #endif /* CONFIG_IPC */
1282 if (hwnd == HWND_BROADCAST)
1284 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1286 TRACE(msg,"HWND_BROADCAST !\n");
1287 for (ppWnd = list; *ppWnd; ppWnd++)
1290 if (!IsWindow32(wndPtr->hwndSelf)) continue;
1291 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
1293 TRACE(msg,"BROADCAST Message to hWnd=%04x m=%04X w=%04lX l=%08lX !\n",
1294 wndPtr->hwndSelf, msg, (DWORD)wParam, lParam);
1295 SendMessage16( wndPtr->hwndSelf, msg, wParam, lParam );
1298 HeapFree( SystemHeap, 0, list );
1299 TRACE(msg,"End of HWND_BROADCAST !\n");
1303 if (HOOK_IsHooked( WH_CALLWNDPROC ))
1307 if ((pmsg = SEGPTR_NEW(CWPSTRUCT16)))
1311 pmsg->wParam = wParam;
1312 pmsg->lParam = lParam;
1313 HOOK_CallHooks16( WH_CALLWNDPROC, HC_ACTION, 1,
1314 (LPARAM)SEGPTR_GET(pmsg) );
1316 msg = pmsg->message;
1317 wParam = pmsg->wParam;
1318 lParam = pmsg->lParam;
1319 SEGPTR_FREE( pmsg );
1323 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
1325 WARN(msg, "invalid hwnd %04x\n", hwnd );
1328 if (QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))
1329 return 0; /* Don't send anything if the task is dying */
1331 SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
1333 if (wndPtr->hmemTaskQ != GetFastQueue())
1334 ret = MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg,
1335 wParam, lParam, 0 );
1337 ret = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
1338 hwnd, msg, wParam, lParam );
1340 SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, ret );
1344 /************************************************************************
1345 * MSG_CallWndProcHook32
1347 static void MSG_CallWndProcHook32( LPMSG32 pmsg, BOOL32 bUnicode )
1351 cwp.lParam = pmsg->lParam;
1352 cwp.wParam = pmsg->wParam;
1353 cwp.message = pmsg->message;
1354 cwp.hwnd = pmsg->hwnd;
1356 if (bUnicode) HOOK_CallHooks32W(WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp);
1357 else HOOK_CallHooks32A( WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp );
1359 pmsg->lParam = cwp.lParam;
1360 pmsg->wParam = cwp.wParam;
1361 pmsg->message = cwp.message;
1362 pmsg->hwnd = cwp.hwnd;
1365 /**********************************************************************
1366 * PostThreadMessage32A (USER32.422)
1370 * Thread-local message queues are not supported.
1373 BOOL32 WINAPI PostThreadMessage32A(DWORD idThread , UINT32 message,
1374 WPARAM32 wParam, LPARAM lParam )
1379 if ((hQueue = GetThreadQueue(idThread)) == 0)
1383 msg.message = message;
1384 msg.wParam = wParam;
1385 msg.lParam = lParam;
1386 msg.time = GetTickCount();
1390 return QUEUE_AddMsg( hQueue, &msg, 0 );
1393 /**********************************************************************
1394 * PostThreadMessage32W (USER32.423)
1398 * Thread-local message queues are not supported.
1401 BOOL32 WINAPI PostThreadMessage32W(DWORD idThread , UINT32 message,
1402 WPARAM32 wParam, LPARAM lParam )
1404 FIXME(sendmsg, "(...): Should do unicode/ascii conversion!\n");
1405 return PostThreadMessage32A(idThread, message, wParam, lParam);
1408 /***********************************************************************
1409 * SendMessage32A (USER32.454)
1411 LRESULT WINAPI SendMessage32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
1415 WND **list, **ppWnd;
1418 if (hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST)
1420 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1422 for (ppWnd = list; *ppWnd; ppWnd++)
1425 if (!IsWindow32(wndPtr->hwndSelf)) continue;
1426 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
1427 SendMessage32A( wndPtr->hwndSelf, msg, wParam, lParam );
1429 HeapFree( SystemHeap, 0, list );
1433 if (HOOK_IsHooked( WH_CALLWNDPROC ))
1434 MSG_CallWndProcHook32( (LPMSG32)&hwnd, FALSE);
1436 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
1438 WARN(msg, "invalid hwnd %08x\n", hwnd );
1442 if (QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))
1443 return 0; /* Don't send anything if the task is dying */
1445 SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
1447 if (wndPtr->hmemTaskQ != GetFastQueue())
1448 ret = MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam,
1451 ret = CallWindowProc32A( (WNDPROC32)wndPtr->winproc,
1452 hwnd, msg, wParam, lParam );
1454 SPY_ExitMessage( SPY_RESULT_OK32, hwnd, msg, ret );
1459 /***********************************************************************
1460 * SendMessage32W (USER32.459) Send Window Message
1462 * Sends a message to the window procedure of the specified window.
1463 * SendMessage() will not return until the called window procedure
1464 * either returns or calls ReplyMessage().
1466 * Use PostMessage() to send message and return immediately. A window
1467 * procedure may use InSendMessage() to detect
1468 * SendMessage()-originated messages.
1470 * Applications which communicate via HWND_BROADCAST may use
1471 * RegisterWindowMessage() to obtain a unique message to avoid conflicts
1472 * with other applications.
1478 LRESULT WINAPI SendMessage32W(
1479 HWND32 hwnd, /* Window to send message to. If HWND_BROADCAST,
1480 the message will be sent to all top-level windows. */
1482 UINT32 msg, /* message */
1483 WPARAM32 wParam, /* message parameter */
1484 LPARAM lParam /* additional message parameter */
1487 WND **list, **ppWnd;
1490 if (hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST)
1492 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1494 for (ppWnd = list; *ppWnd; ppWnd++)
1497 if (!IsWindow32(wndPtr->hwndSelf)) continue;
1498 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
1499 SendMessage32W( wndPtr->hwndSelf, msg, wParam, lParam );
1501 HeapFree( SystemHeap, 0, list );
1505 if (HOOK_IsHooked( WH_CALLWNDPROC ))
1506 MSG_CallWndProcHook32( (LPMSG32)&hwnd, TRUE);
1508 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
1510 WARN(msg, "invalid hwnd %08x\n", hwnd );
1513 if (QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))
1514 return 0; /* Don't send anything if the task is dying */
1516 SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
1518 if (wndPtr->hmemTaskQ != GetFastQueue())
1519 ret = MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam,
1520 QUEUE_SM_WIN32 | QUEUE_SM_UNICODE );
1522 ret = CallWindowProc32W( (WNDPROC32)wndPtr->winproc,
1523 hwnd, msg, wParam, lParam );
1525 SPY_ExitMessage( SPY_RESULT_OK32, hwnd, msg, ret );
1530 /***********************************************************************
1531 * SendMessageTimeout16 (not a WINAPI)
1533 LRESULT WINAPI SendMessageTimeout16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
1534 LPARAM lParam, UINT16 flags,
1535 UINT16 timeout, LPWORD resultp)
1537 FIXME(sendmsg, "(...): semistub\n");
1538 return SendMessage16 (hwnd, msg, wParam, lParam);
1542 /***********************************************************************
1543 * SendMessageTimeout32A (USER32.457)
1545 LRESULT WINAPI SendMessageTimeout32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
1546 LPARAM lParam, UINT32 flags,
1547 UINT32 timeout, LPDWORD resultp)
1549 FIXME(sendmsg, "(...): semistub\n");
1550 return SendMessage32A (hwnd, msg, wParam, lParam);
1554 /***********************************************************************
1555 * SendMessageTimeout32W (USER32.458)
1557 LRESULT WINAPI SendMessageTimeout32W( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
1558 LPARAM lParam, UINT32 flags,
1559 UINT32 timeout, LPDWORD resultp)
1561 FIXME(sendmsg, "(...): semistub\n");
1562 return SendMessage32W (hwnd, msg, wParam, lParam);
1566 /***********************************************************************
1567 * WaitMessage (USER.112) (USER32.578) Suspend thread pending messages
1569 * WaitMessage() suspends a thread until events appear in the thread's
1574 * Is supposed to return BOOL under Win32.
1576 * Thread-local message queues are not supported.
1583 void WINAPI WaitMessage( void )
1585 QUEUE_WaitBits( QS_ALLINPUT );
1588 /***********************************************************************
1589 * MsgWaitForMultipleObjects (USER32.400)
1591 DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, HANDLE32 *pHandles,
1592 BOOL32 fWaitAll, DWORD dwMilliseconds,
1596 HANDLE32 handles[MAXIMUM_WAIT_OBJECTS];
1599 HQUEUE16 hQueue = GetFastQueue();
1600 MESSAGEQUEUE *msgQueue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
1601 if (!msgQueue) return WAIT_FAILED;
1603 if (nCount > MAXIMUM_WAIT_OBJECTS-1)
1605 SetLastError( ERROR_INVALID_PARAMETER );
1606 QUEUE_Unlock( msgQueue );
1610 msgQueue->changeBits = 0;
1611 msgQueue->wakeMask = dwWakeMask;
1613 /* Add the thread event to the handle list */
1614 for (i = 0; i < nCount; i++) handles[i] = pHandles[i];
1615 handles[nCount] = msgQueue->hEvent;
1616 ret = WaitForMultipleObjects( nCount+1, handles, fWaitAll, dwMilliseconds );
1618 QUEUE_Unlock( msgQueue );
1632 static const struct accent_char accent_chars[] =
1634 /* A good idea should be to read /usr/X11/lib/X11/locale/iso8859-x/Compose */
1635 {'`', 'A', '\300'}, {'`', 'a', '\340'},
1636 {'\'', 'A', '\301'}, {'\'', 'a', '\341'},
1637 {'^', 'A', '\302'}, {'^', 'a', '\342'},
1638 {'~', 'A', '\303'}, {'~', 'a', '\343'},
1639 {'"', 'A', '\304'}, {'"', 'a', '\344'},
1640 {'O', 'A', '\305'}, {'o', 'a', '\345'},
1641 {'0', 'A', '\305'}, {'0', 'a', '\345'},
1642 {'A', 'A', '\305'}, {'a', 'a', '\345'},
1643 {'A', 'E', '\306'}, {'a', 'e', '\346'},
1644 {',', 'C', '\307'}, {',', 'c', '\347'},
1645 {'`', 'E', '\310'}, {'`', 'e', '\350'},
1646 {'\'', 'E', '\311'}, {'\'', 'e', '\351'},
1647 {'^', 'E', '\312'}, {'^', 'e', '\352'},
1648 {'"', 'E', '\313'}, {'"', 'e', '\353'},
1649 {'`', 'I', '\314'}, {'`', 'i', '\354'},
1650 {'\'', 'I', '\315'}, {'\'', 'i', '\355'},
1651 {'^', 'I', '\316'}, {'^', 'i', '\356'},
1652 {'"', 'I', '\317'}, {'"', 'i', '\357'},
1653 {'-', 'D', '\320'}, {'-', 'd', '\360'},
1654 {'~', 'N', '\321'}, {'~', 'n', '\361'},
1655 {'`', 'O', '\322'}, {'`', 'o', '\362'},
1656 {'\'', 'O', '\323'}, {'\'', 'o', '\363'},
1657 {'^', 'O', '\324'}, {'^', 'o', '\364'},
1658 {'~', 'O', '\325'}, {'~', 'o', '\365'},
1659 {'"', 'O', '\326'}, {'"', 'o', '\366'},
1660 {'/', 'O', '\330'}, {'/', 'o', '\370'},
1661 {'`', 'U', '\331'}, {'`', 'u', '\371'},
1662 {'\'', 'U', '\332'}, {'\'', 'u', '\372'},
1663 {'^', 'U', '\333'}, {'^', 'u', '\373'},
1664 {'"', 'U', '\334'}, {'"', 'u', '\374'},
1665 {'\'', 'Y', '\335'}, {'\'', 'y', '\375'},
1666 {'T', 'H', '\336'}, {'t', 'h', '\376'},
1667 {'s', 's', '\337'}, {'"', 'y', '\377'},
1668 {'s', 'z', '\337'}, {'i', 'j', '\377'},
1669 /* iso-8859-2 uses this */
1670 {'<', 'L', '\245'}, {'<', 'l', '\265'}, /* caron */
1671 {'<', 'S', '\251'}, {'<', 's', '\271'},
1672 {'<', 'T', '\253'}, {'<', 't', '\273'},
1673 {'<', 'Z', '\256'}, {'<', 'z', '\276'},
1674 {'<', 'C', '\310'}, {'<', 'c', '\350'},
1675 {'<', 'E', '\314'}, {'<', 'e', '\354'},
1676 {'<', 'D', '\317'}, {'<', 'd', '\357'},
1677 {'<', 'N', '\322'}, {'<', 'n', '\362'},
1678 {'<', 'R', '\330'}, {'<', 'r', '\370'},
1679 {';', 'A', '\241'}, {';', 'a', '\261'}, /* ogonek */
1680 {';', 'E', '\312'}, {';', 'e', '\332'},
1681 {'\'', 'Z', '\254'}, {'\'', 'z', '\274'}, /* acute */
1682 {'\'', 'R', '\300'}, {'\'', 'r', '\340'},
1683 {'\'', 'L', '\305'}, {'\'', 'l', '\345'},
1684 {'\'', 'C', '\306'}, {'\'', 'c', '\346'},
1685 {'\'', 'N', '\321'}, {'\'', 'n', '\361'},
1686 /* collision whith S, from iso-8859-9 !!! */
1687 {',', 'S', '\252'}, {',', 's', '\272'}, /* cedilla */
1688 {',', 'T', '\336'}, {',', 't', '\376'},
1689 {'.', 'Z', '\257'}, {'.', 'z', '\277'}, /* dot above */
1690 {'/', 'L', '\243'}, {'/', 'l', '\263'}, /* slash */
1691 {'/', 'D', '\320'}, {'/', 'd', '\360'},
1692 {'(', 'A', '\303'}, {'(', 'a', '\343'}, /* breve */
1693 {'\275', 'O', '\325'}, {'\275', 'o', '\365'}, /* double acute */
1694 {'\275', 'U', '\334'}, {'\275', 'u', '\374'},
1695 {'0', 'U', '\332'}, {'0', 'u', '\372'}, /* ring above */
1696 /* iso-8859-3 uses this */
1697 {'/', 'H', '\241'}, {'/', 'h', '\261'}, /* slash */
1698 {'>', 'H', '\246'}, {'>', 'h', '\266'}, /* circumflex */
1699 {'>', 'J', '\254'}, {'>', 'j', '\274'},
1700 {'>', 'C', '\306'}, {'>', 'c', '\346'},
1701 {'>', 'G', '\330'}, {'>', 'g', '\370'},
1702 {'>', 'S', '\336'}, {'>', 's', '\376'},
1703 /* collision whith G( from iso-8859-9 !!! */
1704 {'(', 'G', '\253'}, {'(', 'g', '\273'}, /* breve */
1705 {'(', 'U', '\335'}, {'(', 'u', '\375'},
1706 /* collision whith I. from iso-8859-3 !!! */
1707 {'.', 'I', '\251'}, {'.', 'i', '\271'}, /* dot above */
1708 {'.', 'C', '\305'}, {'.', 'c', '\345'},
1709 {'.', 'G', '\325'}, {'.', 'g', '\365'},
1710 /* iso-8859-4 uses this */
1711 {',', 'R', '\243'}, {',', 'r', '\263'}, /* cedilla */
1712 {',', 'L', '\246'}, {',', 'l', '\266'},
1713 {',', 'G', '\253'}, {',', 'g', '\273'},
1714 {',', 'N', '\321'}, {',', 'n', '\361'},
1715 {',', 'K', '\323'}, {',', 'k', '\363'},
1716 {'~', 'I', '\245'}, {'~', 'i', '\265'}, /* tilde */
1717 {'-', 'E', '\252'}, {'-', 'e', '\272'}, /* macron */
1718 {'-', 'A', '\300'}, {'-', 'a', '\340'},
1719 {'-', 'I', '\317'}, {'-', 'i', '\357'},
1720 {'-', 'O', '\322'}, {'-', 'o', '\362'},
1721 {'-', 'U', '\336'}, {'-', 'u', '\376'},
1722 {'/', 'T', '\254'}, {'/', 't', '\274'}, /* slash */
1723 {'.', 'E', '\314'}, {'.', 'e', '\344'}, /* dot above */
1724 {';', 'I', '\307'}, {';', 'i', '\347'}, /* ogonek */
1725 {';', 'U', '\331'}, {';', 'u', '\371'},
1726 /* iso-8859-9 uses this */
1727 /* iso-8859-9 has really bad choosen G( S, and I. as they collide
1728 * whith the same letters on other iso-8859-x (that is they are on
1729 * different places :-( ), if you use turkish uncomment these and
1730 * comment out the lines in iso-8859-2 and iso-8859-3 sections
1731 * FIXME: should be dynamic according to chosen language
1732 * if/when Wine has turkish support.
1734 /* collision whith G( from iso-8859-3 !!! */
1735 /* {'(', 'G', '\320'}, {'(', 'g', '\360'}, */ /* breve */
1736 /* collision whith S, from iso-8859-2 !!! */
1737 /* {',', 'S', '\336'}, {',', 's', '\376'}, */ /* cedilla */
1738 /* collision whith I. from iso-8859-3 !!! */
1739 /* {'.', 'I', '\335'}, {'.', 'i', '\375'}, */ /* dot above */
1743 /***********************************************************************
1744 * MSG_DoTranslateMessage
1746 * Implementation of TranslateMessage.
1748 * TranslateMessage translates virtual-key messages into character-messages,
1750 * WM_KEYDOWN/WM_KEYUP combinations produce a WM_CHAR or WM_DEADCHAR message.
1751 * ditto replacing WM_* with WM_SYS*
1752 * This produces WM_CHAR messages only for keys mapped to ASCII characters
1753 * by the keyboard driver.
1755 static BOOL32 MSG_DoTranslateMessage( UINT32 message, HWND32 hwnd,
1756 WPARAM32 wParam, LPARAM lParam )
1758 static int dead_char;
1761 if (message != WM_MOUSEMOVE && message != WM_TIMER)
1762 TRACE(msg, "(%s, %04X, %08lX)\n",
1763 SPY_GetMsgName(message), wParam, lParam );
1764 if(message >= WM_KEYFIRST && message <= WM_KEYLAST)
1765 TRACE(key, "(%s, %04X, %08lX)\n",
1766 SPY_GetMsgName(message), wParam, lParam );
1768 if ((message != WM_KEYDOWN) && (message != WM_SYSKEYDOWN)) return FALSE;
1770 TRACE(key, "Translating key %04X, scancode %04X\n",
1771 wParam, HIWORD(lParam) );
1773 /* FIXME : should handle ToAscii yielding 2 */
1774 switch (ToAscii32(wParam, HIWORD(lParam),
1775 QueueKeyStateTable,(LPWORD)wp, 0))
1778 message = (message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
1779 /* Should dead chars handling go in ToAscii ? */
1784 if (wp[0] == ' ') wp[0] = dead_char;
1785 if (dead_char == 0xa2) dead_char = '(';
1786 else if (dead_char == 0xa8) dead_char = '"';
1787 else if (dead_char == 0xb2) dead_char = ';';
1788 else if (dead_char == 0xb4) dead_char = '\'';
1789 else if (dead_char == 0xb7) dead_char = '<';
1790 else if (dead_char == 0xb8) dead_char = ',';
1791 else if (dead_char == 0xff) dead_char = '.';
1792 for (i = 0; i < sizeof(accent_chars)/sizeof(accent_chars[0]); i++)
1793 if ((accent_chars[i].ac_accent == dead_char) &&
1794 (accent_chars[i].ac_char == wp[0]))
1796 wp[0] = accent_chars[i].ac_result;
1801 TRACE(key, "1 -> PostMessage(%s)\n", SPY_GetMsgName(message));
1802 PostMessage16( hwnd, message, wp[0], lParam );
1806 message = (message == WM_KEYDOWN) ? WM_DEADCHAR : WM_SYSDEADCHAR;
1808 TRACE(key, "-1 -> PostMessage(%s)\n",
1809 SPY_GetMsgName(message));
1810 PostMessage16( hwnd, message, wp[0], lParam );
1817 /***********************************************************************
1818 * TranslateMessage16 (USER.113)
1820 BOOL16 WINAPI TranslateMessage16( const MSG16 *msg )
1822 return MSG_DoTranslateMessage( msg->message, msg->hwnd,
1823 msg->wParam, msg->lParam );
1827 /***********************************************************************
1828 * WIN16_TranslateMessage32 (USER.821)
1830 BOOL16 WINAPI WIN16_TranslateMessage32( const MSG16_32 *msg, BOOL16 wHaveParamHigh )
1835 wParam = MAKELONG(msg->msg.wParam, msg->wParamHigh);
1837 wParam = (WPARAM32)msg->msg.wParam;
1839 return MSG_DoTranslateMessage( msg->msg.message, msg->msg.hwnd,
1840 wParam, msg->msg.lParam );
1843 /***********************************************************************
1844 * TranslateMessage32 (USER32.556)
1846 BOOL32 WINAPI TranslateMessage32( const MSG32 *msg )
1848 return MSG_DoTranslateMessage( msg->message, msg->hwnd,
1849 msg->wParam, msg->lParam );
1853 /***********************************************************************
1854 * DispatchMessage16 (USER.114)
1856 LONG WINAPI DispatchMessage16( const MSG16* msg )
1862 /* Process timer messages */
1863 if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
1867 return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
1868 msg->message, msg->wParam, GetTickCount() );
1872 if (!msg->hwnd) return 0;
1873 if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0;
1874 if (!wndPtr->winproc) return 0;
1875 painting = (msg->message == WM_PAINT);
1876 if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
1878 SPY_EnterMessage( SPY_DISPATCHMESSAGE16, msg->hwnd, msg->message,
1879 msg->wParam, msg->lParam );
1880 retval = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
1881 msg->hwnd, msg->message,
1882 msg->wParam, msg->lParam );
1883 SPY_ExitMessage( SPY_RESULT_OK16, msg->hwnd, msg->message, retval );
1885 if (painting && (wndPtr = WIN_FindWndPtr( msg->hwnd )) &&
1886 (wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate)
1888 ERR(msg, "BeginPaint not called on WM_PAINT for hwnd %04x!\n",
1890 wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
1891 /* Validate the update region to avoid infinite WM_PAINT loop */
1892 ValidateRect32( msg->hwnd, NULL );
1898 /***********************************************************************
1899 * WIN16_DispatchMessage32 (USER.822)
1901 LONG WINAPI WIN16_DispatchMessage32( const MSG16_32* lpmsg16_32, BOOL16 wHaveParamHigh )
1903 if (wHaveParamHigh == FALSE)
1904 return DispatchMessage16(&(lpmsg16_32->msg));
1909 msg.hwnd = lpmsg16_32->msg.hwnd;
1910 msg.message = lpmsg16_32->msg.message;
1911 msg.wParam = MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
1912 msg.lParam = lpmsg16_32->msg.lParam;
1913 msg.time = lpmsg16_32->msg.time;
1914 msg.pt.x = (INT32)lpmsg16_32->msg.pt.x;
1915 msg.pt.y = (INT32)lpmsg16_32->msg.pt.y;
1916 return DispatchMessage32A(&msg);
1920 /***********************************************************************
1921 * DispatchMessage32A (USER32.141)
1923 LONG WINAPI DispatchMessage32A( const MSG32* msg )
1929 /* Process timer messages */
1930 if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
1934 /* HOOK_CallHooks32A( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
1935 return CallWindowProc32A( (WNDPROC32)msg->lParam, msg->hwnd,
1936 msg->message, msg->wParam, GetTickCount() );
1940 if (!msg->hwnd) return 0;
1941 if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0;
1942 if (!wndPtr->winproc) return 0;
1943 painting = (msg->message == WM_PAINT);
1944 if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
1945 /* HOOK_CallHooks32A( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
1947 SPY_EnterMessage( SPY_DISPATCHMESSAGE32, msg->hwnd, msg->message,
1948 msg->wParam, msg->lParam );
1949 retval = CallWindowProc32A( (WNDPROC32)wndPtr->winproc,
1950 msg->hwnd, msg->message,
1951 msg->wParam, msg->lParam );
1952 SPY_ExitMessage( SPY_RESULT_OK32, msg->hwnd, msg->message, retval );
1954 if (painting && (wndPtr = WIN_FindWndPtr( msg->hwnd )) &&
1955 (wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate)
1957 ERR(msg, "BeginPaint not called on WM_PAINT for hwnd %04x!\n",
1959 wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
1960 /* Validate the update region to avoid infinite WM_PAINT loop */
1961 ValidateRect32( msg->hwnd, NULL );
1967 /***********************************************************************
1968 * DispatchMessage32W (USER32.142) Process Message
1970 * Process the message specified in the structure *_msg_.
1972 * If the lpMsg parameter points to a WM_TIMER message and the
1973 * parameter of the WM_TIMER message is not NULL, the lParam parameter
1974 * points to the function that is called instead of the window
1977 * The message must be valid.
1981 * DispatchMessage() returns the result of the window procedure invoked.
1988 LONG WINAPI DispatchMessage32W( const MSG32* msg )
1994 /* Process timer messages */
1995 if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
1999 /* HOOK_CallHooks32W( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
2000 return CallWindowProc32W( (WNDPROC32)msg->lParam, msg->hwnd,
2001 msg->message, msg->wParam, GetTickCount() );
2005 if (!msg->hwnd) return 0;
2006 if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0;
2007 if (!wndPtr->winproc) return 0;
2008 painting = (msg->message == WM_PAINT);
2009 if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
2010 /* HOOK_CallHooks32W( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
2012 SPY_EnterMessage( SPY_DISPATCHMESSAGE32, msg->hwnd, msg->message,
2013 msg->wParam, msg->lParam );
2014 retval = CallWindowProc32W( (WNDPROC32)wndPtr->winproc,
2015 msg->hwnd, msg->message,
2016 msg->wParam, msg->lParam );
2017 SPY_ExitMessage( SPY_RESULT_OK32, msg->hwnd, msg->message, retval );
2019 if (painting && (wndPtr = WIN_FindWndPtr( msg->hwnd )) &&
2020 (wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate)
2022 ERR(msg, "BeginPaint not called on WM_PAINT for hwnd %04x!\n",
2024 wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
2025 /* Validate the update region to avoid infinite WM_PAINT loop */
2026 ValidateRect32( msg->hwnd, NULL );
2032 /***********************************************************************
2033 * RegisterWindowMessage16 (USER.118)
2035 WORD WINAPI RegisterWindowMessage16( SEGPTR str )
2037 TRACE(msg, "%08lx\n", (DWORD)str );
2038 return GlobalAddAtom16( str );
2042 /***********************************************************************
2043 * RegisterWindowMessage32A (USER32.437)
2045 WORD WINAPI RegisterWindowMessage32A( LPCSTR str )
2047 TRACE(msg, "%s\n", str );
2048 return GlobalAddAtom32A( str );
2052 /***********************************************************************
2053 * RegisterWindowMessage32W (USER32.438)
2055 WORD WINAPI RegisterWindowMessage32W( LPCWSTR str )
2057 TRACE(msg, "%p\n", str );
2058 return GlobalAddAtom32W( str );
2062 /***********************************************************************
2063 * GetTickCount (USER.13) (KERNEL32.299) System Time
2064 * Returns the number of milliseconds, modulo 2^32, since the start
2065 * of the current session.
2071 DWORD WINAPI GetTickCount(void)
2074 gettimeofday( &t, NULL );
2075 /* make extremely compatible: granularity is 25 msec */
2076 return ((t.tv_sec * 1000) + (t.tv_usec / 25000) * 25) - MSG_WineStartTicks;
2080 /***********************************************************************
2081 * GetCurrentTime16 (USER.15)
2083 * (effectively identical to GetTickCount)
2085 DWORD WINAPI GetCurrentTime16(void)
2087 return GetTickCount();
2091 /***********************************************************************
2092 * InSendMessage16 (USER.192)
2094 BOOL16 WINAPI InSendMessage16(void)
2096 return InSendMessage32();
2100 /***********************************************************************
2101 * InSendMessage32 (USER32.320)
2103 BOOL32 WINAPI InSendMessage32(void)
2105 MESSAGEQUEUE *queue;
2108 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue() )))
2110 ret = (BOOL32)queue->InSendMessageHandle;
2112 QUEUE_Unlock( queue );
2116 /***********************************************************************
2117 * BroadcastSystemMessage (USER32.12)
2119 LONG WINAPI BroadcastSystemMessage(
2120 DWORD dwFlags,LPDWORD recipients,UINT32 uMessage,WPARAM32 wParam,
2123 FIXME(sendmsg,"(%08lx,%08lx,%08x,%08x,%08lx): stub!\n",
2124 dwFlags,*recipients,uMessage,wParam,lParam
2129 /***********************************************************************
2130 * SendNotifyMessageA (USER32.460)
2132 * The message sended with PostMessage has to be put in the queue
2133 * with a higher priority as the other "Posted" messages.
2134 * QUEUE_AddMsg has to be modifyed.
2136 BOOL32 WINAPI SendNotifyMessage32A(HWND32 hwnd,UINT32 msg,WPARAM32 wParam,LPARAM lParam)
2137 { BOOL32 ret = TRUE;
2138 FIXME(msg,"(%04x,%08x,%08x,%08lx) not complete\n",
2139 hwnd, msg, wParam, lParam);
2141 if ( GetCurrentThreadId() == GetWindowThreadProcessId ( hwnd, NULL))
2142 { ret=SendMessage32A ( hwnd, msg, wParam, lParam );
2145 { PostMessage32A ( hwnd, msg, wParam, lParam );
2150 /***********************************************************************
2151 * SendNotifyMessageW (USER32.461)
2153 * The message sended with PostMessage has to be put in the queue
2154 * with a higher priority as the other "Posted" messages.
2155 * QUEUE_AddMsg has to be modifyed.
2157 BOOL32 WINAPI SendNotifyMessage32W(HWND32 hwnd,UINT32 msg,WPARAM32 wParam,LPARAM lParam)
2158 { BOOL32 ret = TRUE;
2159 FIXME(msg,"(%04x,%08x,%08x,%08lx) not complete\n",
2160 hwnd, msg, wParam, lParam);
2162 if ( GetCurrentThreadId() == GetWindowThreadProcessId ( hwnd, NULL))
2163 { ret=SendMessage32W ( hwnd, msg, wParam, lParam );
2166 { PostMessage32W ( hwnd, msg, wParam, lParam );
2171 /***********************************************************************
2172 * SendMessageCallBack32A
2173 * FIXME: It's like PostMessage. The callback gets called when the message
2174 * is processed. We have to modify the message processing for a exact
2177 BOOL32 WINAPI SendMessageCallBack32A(
2178 HWND32 hWnd,UINT32 Msg,WPARAM32 wParam,LPARAM lParam,
2179 FARPROC32 lpResultCallBack,DWORD dwData)
2181 FIXME(msg,"(0x%04x,0x%04x,0x%08x,0x%08lx,%p,0x%08lx),stub!\n",
2182 hWnd,Msg,wParam,lParam,lpResultCallBack,dwData);
2183 if ( hWnd == HWND_BROADCAST)
2184 { PostMessage32A( hWnd, Msg, wParam, lParam);
2185 FIXME(msg,"Broadcast: Callback will not be called!\n");
2188 (lpResultCallBack)( hWnd, Msg, dwData, SendMessage32A ( hWnd, Msg, wParam, lParam ));