Moved the major part of message queue and window timer handling into
the server.
Implemented MsgWaitForMultipleObjectsEx.
diff --git a/windows/message.c b/windows/message.c
index 5648db3..383281a 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -13,6 +13,7 @@
#include "wine/winbase16.h"
#include "message.h"
#include "winerror.h"
+#include "server.h"
#include "win.h"
#include "heap.h"
#include "hook.h"
@@ -24,6 +25,7 @@
#include "winproc.h"
#include "user.h"
#include "thread.h"
+#include "task.h"
#include "options.h"
#include "controls.h"
#include "struct32.h"
@@ -115,9 +117,9 @@
POINT16 pt;
HANDLE16 hQ = GetFastQueue16();
MESSAGEQUEUE *queue = QUEUE_Lock(hQ);
- BOOL mouseClick = ((message == WM_LBUTTONDOWN) ||
- (message == WM_RBUTTONDOWN) ||
- (message == WM_MBUTTONDOWN))?1:0;
+ int mouseClick = ((message == WM_LBUTTONDOWN) ||
+ (message == WM_RBUTTONDOWN) ||
+ (message == WM_MBUTTONDOWN));
DWORD retvalue;
/* Find the window to dispatch this mouse message to */
@@ -155,7 +157,7 @@
/* Wake up the other task */
QUEUE_Unlock( queue );
queue = QUEUE_Lock( pWnd->hmemTaskQ );
- if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE );
+ if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE, 0 );
QUEUE_Unlock( queue );
retvalue = SYSQ_MSG_ABANDON;
@@ -387,7 +389,7 @@
/* Wake up the other task */
queue = QUEUE_Lock( pWnd->hmemTaskQ );
- if (queue) QUEUE_SetWakeBit( queue, QS_KEY );
+ if (queue) QUEUE_SetWakeBit( queue, QS_KEY, 0 );
QUEUE_Unlock( queue );
WIN_ReleaseWndPtr(pWnd);
return SYSQ_MSG_ABANDON;
@@ -771,127 +773,59 @@
static LRESULT MSG_SendMessageInterThread( HQUEUE16 hDestQueue,
HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam,
- DWORD timeout, WORD flags,
+ DWORD timeout, WORD type,
LRESULT *pRes)
{
- MESSAGEQUEUE *queue, *destQ;
- SMSG *smsg;
- LRESULT retVal = 1;
- int iWndsLocks;
-
- if (pRes) *pRes = 0;
+ MESSAGEQUEUE *destQ;
+ BOOL ret;
+ int iWndsLocks;
+ LRESULT result = 0;
- if (IsTaskLocked16() || !IsWindow(hwnd))
- return 0;
+ TRACE( "hwnd %x msg %x (%s) wp %x lp %lx\n", hwnd, msg, SPY_GetMsgName(msg), wParam, lParam );
- /* create a SMSG structure to hold SendMessage() parameters */
- if (! (smsg = (SMSG *) HeapAlloc( GetProcessHeap(), 0, sizeof(SMSG) )) )
- return 0;
- if (!(queue = QUEUE_Lock( GetFastQueue16() ))) return 0;
+ if (!(destQ = QUEUE_Lock( hDestQueue ))) return 0;
- if (!(destQ = QUEUE_Lock( hDestQueue )))
+ SERVER_START_REQ( send_message )
{
- QUEUE_Unlock( queue );
- return 0;
+ req->posted = FALSE;
+ req->id = destQ->teb->tid;
+ req->type = type;
+ req->win = hwnd;
+ req->msg = msg;
+ req->wparam = wParam;
+ req->lparam = lParam;
+ req->info = 0;
+ ret = !SERVER_CALL_ERR();
}
-
- TRACE_(sendmsg)("SM: %s [%04x] (%04x -> %04x)\n",
- SPY_GetMsgName(msg), msg, queue->self, hDestQueue );
-
- /* fill up SMSG structure */
- smsg->hWnd = hwnd;
- smsg->msg = msg;
- smsg->wParam = wParam;
- smsg->lParam = lParam;
-
- smsg->lResult = 0;
- smsg->hSrcQueue = pRes ? GetFastQueue16() : 0;
- smsg->hDstQueue = hDestQueue;
- smsg->flags = flags;
-
- if (pRes) {
- /* add smsg struct in the processing SM list of the source queue */
- QUEUE_AddSMSG(queue, SM_PROCESSING_LIST, smsg);
- } else {
- /* this is a notification message, we don't need a reply */
- smsg->flags |= SMSG_ALREADY_REPLIED | SMSG_RECEIVER_CLEANS;
- }
-
- /* add smsg struct in the pending list of the destination queue */
- if (QUEUE_AddSMSG(destQ, SM_PENDING_LIST, smsg) == FALSE)
- {
- retVal = 0;
- goto CLEANUP;
- }
-
- if (!pRes) goto CLEANUP; /* don't need a reply */
+ SERVER_END_REQ;
+ QUEUE_Unlock( destQ );
+ if (!ret) return 0;
iWndsLocks = WIN_SuspendWndsLock();
/* wait for the result */
- while ( TRUE )
+ QUEUE_WaitBits( QS_SMRESULT, timeout );
+
+ SERVER_START_REQ( get_message_reply )
{
- /*
- * The sequence is crucial to avoid deadlock situations:
- * - first, we clear the QS_SMRESULT bit
- * - then, we check the SMSG_HAVE_RESULT bit
- * - only if this isn't set, we enter the wait state.
- *
- * As the receiver first sets the SMSG_HAVE_RESULT and then wakes us,
- * we are guaranteed that -should we now clear the QS_SMRESULT that
- * was signalled already by the receiver- we will not start waiting.
- */
-
- if ( smsg->flags & SMSG_HAVE_RESULT )
- {
-got:
- *pRes = smsg->lResult;
- TRACE_(sendmsg)("smResult = %08x\n", (unsigned)*pRes );
- break;
- }
-
- QUEUE_ClearWakeBit( queue, QS_SMRESULT );
-
- if ( smsg->flags & SMSG_HAVE_RESULT )
- goto got;
-
- if( QUEUE_WaitBits( QS_SMRESULT, timeout ) == 0 )
- {
- /* return with timeout */
- SetLastError( 0 );
- retVal = 0;
- break;
- }
+ req->cancel = 1;
+ if ((ret = !SERVER_CALL_ERR())) result = req->result;
}
+ SERVER_END_REQ;
+
+ TRACE( "hwnd %x msg %x (%s) wp %x lp %lx got reply %lx (err=%ld)\n",
+ hwnd, msg, SPY_GetMsgName(msg), wParam, lParam, result, GetLastError() );
+
+ if (!ret && (GetLastError() == ERROR_IO_PENDING))
+ {
+ if (timeout == INFINITE) ERR("no timeout but no result\n");
+ SetLastError(0); /* timeout */
+ }
+
+ if (pRes) *pRes = result;
+
WIN_RestoreWndsLock(iWndsLocks);
-
- /* remove the smsg from the processing list of the source queue */
- QUEUE_RemoveSMSG( queue, SM_PROCESSING_LIST, smsg );
-
- /* Note: the destination thread is in charge of removing the smsg from
- the pending list */
-
- /* In the case of an early reply (or a timeout), sender thread will
- released the smsg structure if the receiver thread is done
- (SMSG_RECEIVED set). If the receiver thread isn't done,
- SMSG_RECEIVER_CLEANS_UP flag is set, and it will be the receiver
- responsibility to release smsg */
- EnterCriticalSection( &queue->cSection );
-
- if (smsg->flags & SMSG_RECEIVED)
- HeapFree(GetProcessHeap(), 0, smsg);
- else
- smsg->flags |= SMSG_RECEIVER_CLEANS;
-
- LeaveCriticalSection( &queue->cSection );
-
-
-CLEANUP:
- QUEUE_Unlock( queue );
- QUEUE_Unlock( destQ );
-
- TRACE_(sendmsg)("done!\n");
- return retVal;
+ return ret;
}
@@ -908,77 +842,14 @@
*/
BOOL WINAPI ReplyMessage( LRESULT result )
{
- MESSAGEQUEUE *senderQ = 0;
- MESSAGEQUEUE *queue = 0;
- SMSG *smsg;
- BOOL ret = FALSE;
-
- if (!(queue = QUEUE_Lock( GetFastQueue16() )))
- return FALSE;
-
- TRACE_(sendmsg)("ReplyMessage, queue %04x\n", queue->self);
-
-
- if ( !(smsg = queue->smWaiting)
- || !( (senderQ = QUEUE_Lock( smsg->hSrcQueue ))
- || (smsg->flags & SMSG_ALREADY_REPLIED)) )
- goto ReplyMessageEnd;
-
- if ( !(smsg->flags & SMSG_ALREADY_REPLIED) )
+ BOOL ret;
+ SERVER_START_REQ( reply_message )
{
- /* This is the first reply, so pass result to sender */
-
- TRACE_(sendmsg)("\trpm: smResult = %08lx\n", (long) result );
-
- EnterCriticalSection(&senderQ->cSection);
-
- smsg->lResult = result;
- smsg->flags |= SMSG_ALREADY_REPLIED;
-
- /* check if it's an early reply (called by the application) or
- a regular reply (called by ReceiveMessage) */
- if ( !(smsg->flags & SMSG_SENDING_REPLY) )
- smsg->flags |= SMSG_EARLY_REPLY;
-
- smsg->flags |= SMSG_HAVE_RESULT;
-
- LeaveCriticalSection(&senderQ->cSection);
-
- /* tell the sending task that its reply is ready */
- QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
-
- ret = TRUE;
+ req->result = result;
+ req->remove = 0;
+ ret = !SERVER_CALL_ERR();
}
-
- if (smsg->flags & SMSG_SENDING_REPLY)
- {
- /* remove msg from the waiting list, since this is the last
- ReplyMessage */
- QUEUE_RemoveSMSG( queue, SM_WAITING_LIST, smsg );
-
- if (senderQ) EnterCriticalSection(&senderQ->cSection);
-
- /* tell the sender we're all done with smsg structure */
- smsg->flags |= SMSG_RECEIVED;
-
- /* sender will set SMSG_RECEIVER_CLEANS_UP if it wants the
- receiver to clean up smsg, it could only happen when there is
- an early reply or a timeout */
- if ( smsg->flags & SMSG_RECEIVER_CLEANS )
- {
- TRACE_(sendmsg)("Receiver cleans up!\n" );
- HeapFree( GetProcessHeap(), 0, smsg );
- }
-
- if (senderQ) LeaveCriticalSection(&senderQ->cSection);
- }
-
-ReplyMessageEnd:
- if ( senderQ )
- QUEUE_Unlock( senderQ );
- if ( queue )
- QUEUE_Unlock( queue );
-
+ SERVER_END_REQ;
return ret;
}
@@ -1116,9 +987,9 @@
iWndsLocks = WIN_SuspendWndsLock();
while(1)
- {
- QMSG *qmsg;
-
+ {
+ WORD wakeBits = HIWORD(GetQueueStatus( mask ));
+
hQueue = GetFastQueue16();
msgQueue = QUEUE_Lock( hQueue );
if (!msgQueue)
@@ -1127,10 +998,7 @@
return FALSE;
}
- EnterCriticalSection( &msgQueue->cSection );
- msgQueue->changeBits = 0;
- LeaveCriticalSection( &msgQueue->cSection );
-
+#if 0
/* First handle a message put by SendMessage() */
while ( QUEUE_ReceiveMessage( msgQueue ) )
@@ -1152,36 +1020,69 @@
break;
}
LeaveCriticalSection( &msgQueue->cSection );
-
+#endif
+
/* Now find a normal message */
retry:
- if ((QUEUE_TestWakeBit(msgQueue, mask & QS_POSTMESSAGE)) &&
- ((qmsg = QUEUE_FindMsg( msgQueue, hwnd, first, last )) != 0))
+ if (wakeBits & (QS_POSTMESSAGE|QS_TIMER|QS_PAINT))
{
- /* Try to convert message to requested type */
- MSG tmpMsg = qmsg->msg;
- if ( !MSG_ConvertMsg( &tmpMsg, qmsg->type, type ) )
+ QMSG qmsg;
+ if (QUEUE_FindMsg( hwnd, first, last, flags & PM_REMOVE, FALSE, &qmsg ))
{
- ERR( "Message %s of wrong type contains pointer parameters. Skipped!\n",
- SPY_GetMsgName(tmpMsg.message));
- QUEUE_RemoveMsg( msgQueue, qmsg );
- goto retry;
+ /* Try to convert message to requested type */
+ MSG tmpMsg = qmsg.msg;
+ if ( !MSG_ConvertMsg( &tmpMsg, qmsg.type, type ) )
+ {
+ ERR( "Message %s of wrong type contains pointer parameters. Skipped!\n",
+ SPY_GetMsgName(tmpMsg.message));
+ /* remove it (FIXME) */
+ if (!(flags & PM_REMOVE)) QUEUE_FindMsg( hwnd, first, last, TRUE, FALSE, &qmsg );
+ goto retry;
+ }
+
+ msg = tmpMsg;
+ msgQueue->GetMessageTimeVal = msg.time;
+ msgQueue->GetMessagePosVal = MAKELONG( (INT16)msg.pt.x, (INT16)msg.pt.y );
+ msgQueue->GetMessageExtraInfoVal = qmsg.extraInfo;
+
+ /* need to fill the window handle for WM_PAINT message */
+ if (msg.message == WM_PAINT)
+ {
+ WND* wndPtr;
+ msg.hwnd = WIN_FindWinToRepaint( hwnd , hQueue );
+ if ((wndPtr = WIN_FindWndPtr(msg.hwnd)))
+ {
+ if( wndPtr->dwStyle & WS_MINIMIZE &&
+ (HICON) GetClassLongA(wndPtr->hwndSelf, GCL_HICON) )
+ {
+ msg.message = WM_PAINTICON;
+ msg.wParam = 1;
+ }
+
+ if( !hwnd || msg.hwnd == hwnd || IsChild16(hwnd,msg.hwnd) )
+ {
+ if( wndPtr->flags & WIN_INTERNAL_PAINT && !wndPtr->hrgnUpdate)
+ {
+ wndPtr->flags &= ~WIN_INTERNAL_PAINT;
+ QUEUE_DecPaintCount( hQueue );
+ }
+ WIN_ReleaseWndPtr(wndPtr);
+ break;
+ }
+ WIN_ReleaseWndPtr(wndPtr);
+ }
+ }
+ else break;
}
-
- msg = tmpMsg;
- msgQueue->GetMessageTimeVal = msg.time;
- msgQueue->GetMessagePosVal = MAKELONG( (INT16)msg.pt.x, (INT16)msg.pt.y );
- msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
-
- if (flags & PM_REMOVE) QUEUE_RemoveMsg( msgQueue, qmsg );
- break;
}
changeBits = MSG_JournalPlayBackMsg();
+#if 0 /* FIXME */
EnterCriticalSection( &msgQueue->cSection );
msgQueue->changeBits |= changeBits;
LeaveCriticalSection( &msgQueue->cSection );
+#endif
/* Now find a hardware event */
@@ -1194,68 +1095,14 @@
break;
}
- /* Check again for SendMessage */
-
- while ( QUEUE_ReceiveMessage( msgQueue ) )
- ;
-
- /* Now find a WM_PAINT message */
-
- if (QUEUE_TestWakeBit(msgQueue, mask & QS_PAINT))
- {
- WND* wndPtr;
- msg.hwnd = WIN_FindWinToRepaint( hwnd , hQueue );
- msg.message = WM_PAINT;
- msg.wParam = 0;
- msg.lParam = 0;
-
- if ((wndPtr = WIN_FindWndPtr(msg.hwnd)))
- {
- if( wndPtr->dwStyle & WS_MINIMIZE &&
- (HICON) GetClassLongA(wndPtr->hwndSelf, GCL_HICON) )
- {
- msg.message = WM_PAINTICON;
- msg.wParam = 1;
- }
-
- if( !hwnd || msg.hwnd == hwnd || IsChild16(hwnd,msg.hwnd) )
- {
- if( wndPtr->flags & WIN_INTERNAL_PAINT && !wndPtr->hrgnUpdate)
- {
- wndPtr->flags &= ~WIN_INTERNAL_PAINT;
- QUEUE_DecPaintCount( hQueue );
- }
- WIN_ReleaseWndPtr(wndPtr);
- break;
- }
- WIN_ReleaseWndPtr(wndPtr);
- }
- }
-
- /* Check for timer messages, but yield first */
-
-#if 0 /* FIXME */
- if (!(flags & PM_NOYIELD))
- {
- UserYield16();
- while ( QUEUE_ReceiveMessage( msgQueue ) )
- ;
- }
-#endif
-
- if (QUEUE_TestWakeBit(msgQueue, mask & QS_TIMER))
- {
- if (TIMER_GetTimerMsg(&msg, hwnd, hQueue, flags & PM_REMOVE)) break;
- }
-
if (peek)
{
#if 0 /* FIXME */
if (!(flags & PM_NOYIELD)) UserYield16();
#endif
/* check for graphics events */
- if (USER_Driver.pMsgWaitForMultipleObjects)
- USER_Driver.pMsgWaitForMultipleObjects( 0, NULL, FALSE, 0 );
+ if (USER_Driver.pMsgWaitForMultipleObjectsEx)
+ USER_Driver.pMsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, 0 );
QUEUE_Unlock( msgQueue );
WIN_RestoreWndsLock(iWndsLocks);
@@ -1556,23 +1403,38 @@
/***********************************************************************
* MSG_PostToQueue
*/
-static BOOL MSG_PostToQueue( HQUEUE16 hQueue, int type, HWND hwnd,
+static BOOL MSG_PostToQueue( DWORD tid, int type, HWND hwnd,
UINT message, WPARAM wParam, LPARAM lParam )
{
- MSG msg;
+ unsigned int res;
- if ( !hQueue ) return FALSE;
+ TRACE( "posting %x %x (%s) %x %lx\n", hwnd, message, SPY_GetMsgName(message), wParam, lParam );
- msg.hwnd = hwnd;
- msg.message = message;
- msg.wParam = wParam;
- msg.lParam = lParam;
- msg.time = GetTickCount();
- GetCursorPos(&msg.pt);
+ SERVER_START_REQ( send_message )
+ {
+ req->posted = TRUE;
+ req->id = (void *)tid;
+ req->type = type;
+ req->win = hwnd;
+ req->msg = message;
+ req->wparam = wParam;
+ req->lparam = lParam;
+ req->info = 0;
+ res = SERVER_CALL();
+ }
+ SERVER_END_REQ;
- return QUEUE_AddMsg( hQueue, type, &msg, 0 );
+ if (res)
+ {
+ if (res == STATUS_INVALID_PARAMETER)
+ SetLastError( ERROR_INVALID_THREAD_ID );
+ else
+ SetLastError( RtlNtStatusToDosError(res) );
+ }
+ return !res;
}
+
/***********************************************************************
* MSG_IsPointerMessage
*
@@ -1652,7 +1514,6 @@
static BOOL MSG_PostMessage( int type, HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam )
{
- HQUEUE16 hQueue;
WND *wndPtr;
/* See thread on wine-devel around 6.2.2001. Basically posted messages
@@ -1680,7 +1541,7 @@
{
TRACE("BROADCAST Message to hWnd=%04x m=%04X w=%04X l=%08lX !\n",
wndPtr->hwndSelf, message, wParam, lParam);
- MSG_PostToQueue( wndPtr->hmemTaskQ, type,
+ MSG_PostToQueue( GetWindowThreadProcessId( wndPtr->hwndSelf, NULL ), type,
wndPtr->hwndSelf, message, wParam, lParam );
}
}
@@ -1689,11 +1550,8 @@
return TRUE;
}
- wndPtr = WIN_FindWndPtr( hwnd );
- hQueue = wndPtr? wndPtr->hmemTaskQ : 0;
- WIN_ReleaseWndPtr(wndPtr);
-
- return MSG_PostToQueue( hQueue, type, hwnd, message, wParam, lParam );
+ return MSG_PostToQueue( GetWindowThreadProcessId( hwnd, NULL ),
+ type, hwnd, message, wParam, lParam );
}
/***********************************************************************
@@ -1730,8 +1588,9 @@
BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 message,
WPARAM16 wParam, LPARAM lParam )
{
- return MSG_PostToQueue( GetTaskQueue16(hTask), QMSG_WIN16,
- 0, message, wParam, lParam );
+ TDB *pTask = TASK_GetPtr( hTask );
+ if (!pTask) return FALSE;
+ return MSG_PostToQueue( (DWORD)pTask->teb->tid, QMSG_WIN16, 0, message, wParam, lParam );
}
/**********************************************************************
@@ -1740,8 +1599,7 @@
BOOL WINAPI PostThreadMessageA( DWORD idThread, UINT message,
WPARAM wParam, LPARAM lParam )
{
- return MSG_PostToQueue( GetThreadQueue16(idThread), QMSG_WIN32A,
- 0, message, wParam, lParam );
+ return MSG_PostToQueue( idThread, QMSG_WIN32A, 0, message, wParam, lParam );
}
/**********************************************************************
@@ -1750,8 +1608,7 @@
BOOL WINAPI PostThreadMessageW( DWORD idThread, UINT message,
WPARAM wParam, LPARAM lParam )
{
- return MSG_PostToQueue( GetThreadQueue16(idThread), QMSG_WIN32W,
- 0, message, wParam, lParam );
+ return MSG_PostToQueue( idThread, QMSG_WIN32W, 0, message, wParam, lParam );
}
@@ -1784,7 +1641,7 @@
* 1 otherwise
*/
static LRESULT MSG_SendMessage( HWND hwnd, UINT msg, WPARAM wParam,
- LPARAM lParam, DWORD timeout, WORD flags,
+ LPARAM lParam, DWORD timeout, WORD type,
LRESULT *pRes)
{
WND * wndPtr = 0;
@@ -1814,7 +1671,7 @@
TRACE("BROADCAST Message to hWnd=%04x m=%04X w=%04lX l=%08lX !\n",
wndPtr->hwndSelf, msg, (DWORD)wParam, lParam);
MSG_SendMessage( wndPtr->hwndSelf, msg, wParam, lParam,
- timeout, flags, pRes);
+ timeout, type, pRes);
}
}
WIN_ReleaseWndPtr(wndPtr);
@@ -1825,29 +1682,35 @@
if (HOOK_IsHooked( WH_CALLWNDPROC ))
{
- if (flags & SMSG_UNICODE)
- MSG_CallWndProcHook( (LPMSG)&hwnd, TRUE);
- else if (flags & SMSG_WIN32)
- MSG_CallWndProcHook( (LPMSG)&hwnd, FALSE);
- else
+ switch(type)
{
- LPCWPSTRUCT16 pmsg;
+ case QMSG_WIN16:
+ {
+ LPCWPSTRUCT16 pmsg;
- if ((pmsg = SEGPTR_NEW(CWPSTRUCT16)))
- {
- pmsg->hwnd = hwnd & 0xffff;
- pmsg->message= msg & 0xffff;
- pmsg->wParam = wParam & 0xffff;
- pmsg->lParam = lParam;
- HOOK_CallHooks16( WH_CALLWNDPROC, HC_ACTION, 1,
- (LPARAM)SEGPTR_GET(pmsg) );
- hwnd = pmsg->hwnd;
- msg = pmsg->message;
- wParam = pmsg->wParam;
- lParam = pmsg->lParam;
- SEGPTR_FREE( pmsg );
- }
- }
+ if ((pmsg = SEGPTR_NEW(CWPSTRUCT16)))
+ {
+ pmsg->hwnd = hwnd & 0xffff;
+ pmsg->message= msg & 0xffff;
+ pmsg->wParam = wParam & 0xffff;
+ pmsg->lParam = lParam;
+ HOOK_CallHooks16( WH_CALLWNDPROC, HC_ACTION, 1,
+ (LPARAM)SEGPTR_GET(pmsg) );
+ hwnd = pmsg->hwnd;
+ msg = pmsg->message;
+ wParam = pmsg->wParam;
+ lParam = pmsg->lParam;
+ SEGPTR_FREE( pmsg );
+ }
+ }
+ break;
+ case QMSG_WIN32A:
+ MSG_CallWndProcHook( (LPMSG)&hwnd, FALSE);
+ break;
+ case QMSG_WIN32W:
+ MSG_CallWndProcHook( (LPMSG)&hwnd, TRUE);
+ break;
+ }
}
if (!(wndPtr = WIN_FindWndPtr( hwnd )))
@@ -1860,33 +1723,35 @@
ret = 0; /* Don't send anything if the task is dying */
goto END;
}
- if (flags & SMSG_WIN32)
+ if (type != QMSG_WIN16)
SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wParam, lParam );
else
SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
if (wndPtr->hmemTaskQ && wndPtr->hmemTaskQ != GetFastQueue16())
ret = MSG_SendMessageInterThread( wndPtr->hmemTaskQ, hwnd, msg,
- wParam, lParam, timeout, flags, pRes );
+ wParam, lParam, timeout, type, pRes );
else
{
- LRESULT res;
+ LRESULT res = 0;
/* Call the right CallWindowProc flavor */
- if (flags & SMSG_UNICODE)
- res = CallWindowProcW( (WNDPROC)wndPtr->winproc,
- hwnd, msg, wParam, lParam );
- else if (flags & SMSG_WIN32)
- res = CallWindowProcA( (WNDPROC)wndPtr->winproc,
- hwnd, msg, wParam, lParam );
- else
- res = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
- (HWND16) hwnd, (UINT16) msg,
- (WPARAM16) wParam, lParam );
+ switch(type)
+ {
+ case QMSG_WIN16:
+ res = CallWindowProc16( (WNDPROC16)wndPtr->winproc, hwnd, msg, wParam, lParam );
+ break;
+ case QMSG_WIN32A:
+ res = CallWindowProcA( (WNDPROC)wndPtr->winproc, hwnd, msg, wParam, lParam );
+ break;
+ case QMSG_WIN32W:
+ res = CallWindowProcW( (WNDPROC)wndPtr->winproc, hwnd, msg, wParam, lParam );
+ break;
+ }
if (pRes) *pRes = res;
}
- if (flags & SMSG_WIN32)
+ if (type != QMSG_WIN16)
SPY_ExitMessage( SPY_RESULT_OK, hwnd, msg, pRes?*pRes:0, wParam, lParam );
else
SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, pRes?*pRes:0, wParam, lParam );
@@ -1903,7 +1768,7 @@
LPARAM lParam)
{
LRESULT res;
- MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, 0, &res);
+ MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, QMSG_WIN16, &res);
return res;
}
@@ -1916,8 +1781,7 @@
{
LRESULT res;
- MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE,
- SMSG_WIN32, &res);
+ MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, QMSG_WIN32A, &res);
return res;
}
@@ -1952,8 +1816,7 @@
) {
LRESULT res;
- MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE,
- SMSG_WIN32 | SMSG_UNICODE, &res);
+ MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, QMSG_WIN32W, &res);
return res;
}
@@ -1971,7 +1834,7 @@
/* FIXME: need support for SMTO_BLOCK */
- ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, 0, &msgRet);
+ ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, QMSG_WIN16, &msgRet);
if (resultp) *resultp = (WORD) msgRet;
return ret;
}
@@ -1989,8 +1852,7 @@
/* FIXME: need support for SMTO_BLOCK */
- ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, SMSG_WIN32,
- &msgRet);
+ ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, QMSG_WIN32A, &msgRet);
if (resultp) *resultp = (DWORD) msgRet;
return ret;
@@ -2009,8 +1871,7 @@
/* FIXME: need support for SMTO_BLOCK */
- ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout,
- SMSG_WIN32 | SMSG_UNICODE, &msgRet);
+ ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, QMSG_WIN32W, &msgRet);
if (resultp) *resultp = (DWORD) msgRet;
return ret;
@@ -2022,77 +1883,82 @@
*
* WaitMessage() suspends a thread until events appear in the thread's
* queue.
- *
- * BUGS
- *
- * Is supposed to return BOOL under Win32.
- *
- * Thread-local message queues are not supported.
- *
- * CONFORMANCE
- *
- * ECMA-234, Win32
- *
*/
-void WINAPI WaitMessage( void )
+BOOL WINAPI WaitMessage(void)
{
- QUEUE_WaitBits( QS_ALLINPUT, INFINITE );
+ return (MsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, QS_ALLINPUT, 0 ) != WAIT_FAILED);
}
+
/***********************************************************************
- * MsgWaitForMultipleObjects (USER32.@)
+ * MsgWaitForMultipleObjectsEx (USER32.@)
*/
-DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, HANDLE *pHandles,
- BOOL fWaitAll, DWORD dwMilliseconds,
- DWORD dwWakeMask )
+DWORD WINAPI MsgWaitForMultipleObjectsEx( DWORD count, CONST HANDLE *pHandles,
+ DWORD timeout, DWORD mask, DWORD flags )
{
- DWORD i;
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
- DWORD ret;
-
+ DWORD i, ret;
HQUEUE16 hQueue = GetFastQueue16();
- MESSAGEQUEUE *msgQueue = QUEUE_Lock( hQueue );
- if (!msgQueue) return WAIT_FAILED;
+ MESSAGEQUEUE *msgQueue;
- if (nCount > MAXIMUM_WAIT_OBJECTS-1)
+ if (count > MAXIMUM_WAIT_OBJECTS-1)
{
SetLastError( ERROR_INVALID_PARAMETER );
- QUEUE_Unlock( msgQueue );
return WAIT_FAILED;
}
- EnterCriticalSection( &msgQueue->cSection );
- msgQueue->changeBits = 0;
- msgQueue->wakeMask = dwWakeMask;
- LeaveCriticalSection( &msgQueue->cSection );
+ if (!(msgQueue = QUEUE_Lock( hQueue ))) return WAIT_FAILED;
+
+ /* set the queue mask */
+ SERVER_START_REQ( set_queue_mask )
+ {
+ req->wake_mask = (flags & MWMO_INPUTAVAILABLE) ? mask : 0;
+ req->changed_mask = mask;
+ req->skip_wait = 0;
+ SERVER_CALL();
+ }
+ SERVER_END_REQ;
/* Add the thread event to the handle list */
- for (i = 0; i < nCount; i++) handles[i] = pHandles[i];
- handles[nCount] = msgQueue->server_queue;
- if (USER_Driver.pMsgWaitForMultipleObjects)
+ for (i = 0; i < count; i++) handles[i] = pHandles[i];
+ handles[count] = msgQueue->server_queue;
+
+
+ if (USER_Driver.pMsgWaitForMultipleObjectsEx)
{
- ret = USER_Driver.pMsgWaitForMultipleObjects(nCount+1, handles, fWaitAll, dwMilliseconds);
- if (ret == nCount+1) ret = nCount; /* pretend the msg queue is ready */
+ ret = USER_Driver.pMsgWaitForMultipleObjectsEx( count+1, handles, timeout, mask, flags );
+ if (ret == count+1) ret = count; /* pretend the msg queue is ready */
}
else
- ret = WaitForMultipleObjects( nCount+1, handles, fWaitAll, dwMilliseconds );
-
+ ret = WaitForMultipleObjectsEx( count+1, handles, flags & MWMO_WAITALL,
+ timeout, flags & MWMO_ALERTABLE );
QUEUE_Unlock( msgQueue );
return ret;
}
+
/***********************************************************************
- * MsgWaitForMultipleObjects (USER.640)
+ * MsgWaitForMultipleObjects (USER32.@)
*/
-DWORD WINAPI MsgWaitForMultipleObjects16( DWORD nCount, HANDLE *pHandles,
- BOOL fWaitAll, DWORD dwMilliseconds,
- DWORD dwWakeMask )
+DWORD WINAPI MsgWaitForMultipleObjects( DWORD count, CONST HANDLE *handles,
+ BOOL wait_all, DWORD timeout, DWORD mask )
{
- TRACE("(%lu,%p,%u,%lu,0x%lx)\n",
- nCount, pHandles, fWaitAll, dwMilliseconds, dwWakeMask);
- return MsgWaitForMultipleObjects(nCount, pHandles, fWaitAll, dwMilliseconds, dwWakeMask);
+ return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
+ wait_all ? MWMO_WAITALL : 0 );
}
+
+/***********************************************************************
+ * MsgWaitForMultipleObjects16 (USER.640)
+ */
+DWORD WINAPI MsgWaitForMultipleObjects16( DWORD count, CONST HANDLE *handles,
+ BOOL wait_all, DWORD timeout, DWORD mask )
+{
+ return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
+ wait_all ? MWMO_WAITALL : 0 );
+}
+
+
struct accent_char
{
BYTE ac_accent;
@@ -2594,17 +2460,25 @@
*/
BOOL WINAPI InSendMessage(void)
{
- MESSAGEQUEUE *queue;
- BOOL ret;
+ return (InSendMessageEx(NULL) & (ISMEX_SEND|ISMEX_REPLIED)) == ISMEX_SEND;
+}
- if (!(queue = QUEUE_Lock( GetFastQueue16() )))
- return 0;
- ret = (BOOL)queue->smWaiting;
- QUEUE_Unlock( queue );
+/***********************************************************************
+ * InSendMessageEx (USER32.@)
+ */
+DWORD WINAPI InSendMessageEx( LPVOID reserved )
+{
+ DWORD ret = 0;
+ SERVER_START_REQ( in_send_message )
+ {
+ if (!SERVER_CALL_ERR()) ret = req->flags;
+ }
+ SERVER_END_REQ;
return ret;
}
+
/***********************************************************************
* BroadcastSystemMessage (USER32.@)
*/
@@ -2623,8 +2497,7 @@
*/
BOOL WINAPI SendNotifyMessageA(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
- return MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE,
- SMSG_WIN32, NULL);
+ return MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, QMSG_WIN32A, NULL);
}
/***********************************************************************
@@ -2632,8 +2505,7 @@
*/
BOOL WINAPI SendNotifyMessageW(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
- return MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE,
- SMSG_WIN32 | SMSG_UNICODE, NULL);
+ return MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, QMSG_WIN32W, NULL);
}
/***********************************************************************