Implemented SendMessageTimeout() functions.

This commit is contained in:
Stephane Lussier 1999-03-10 16:21:12 +00:00 committed by Alexandre Julliard
parent ebe76b73a9
commit bae5552a14
3 changed files with 256 additions and 268 deletions

View File

@ -152,7 +152,7 @@ extern MESSAGEQUEUE *QUEUE_GetSysQueue(void);
extern void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit );
extern void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit );
extern void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue );
extern void QUEUE_WaitBits( WORD bits );
extern int QUEUE_WaitBits( WORD bits, DWORD timeout );
extern void QUEUE_IncPaintCount( HQUEUE16 hQueue );
extern void QUEUE_DecPaintCount( HQUEUE16 hQueue );
extern void QUEUE_IncTimerCount( HQUEUE16 hQueue );

View File

@ -44,7 +44,6 @@ DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
static UINT doubleClickSpeed = 452;
/***********************************************************************
* MSG_CheckFilter
*/
@ -617,16 +616,24 @@ UINT WINAPI GetDoubleClickTime(void)
/***********************************************************************
* MSG_SendMessage
* MSG_SendMessageInterThread
*
* Implementation of an inter-task SendMessage.
* Return values:
* 0 if error or timeout
* 1 if successflul
*/
static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam, WORD flags )
static LRESULT MSG_SendMessageInterThread( HQUEUE16 hDestQueue,
HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam,
DWORD timeout, WORD flags,
LRESULT *pRes)
{
MESSAGEQUEUE *queue, *destQ;
SMSG *smsg;
LRESULT lResult = 0;
LRESULT retVal = 1;
*pRes = 0;
if (IsTaskLocked16() || !IsWindow(hwnd))
return 0;
@ -634,7 +641,6 @@ static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND hwnd, UINT msg,
/* create a SMSG structure to hold SendMessage() parameters */
if (! (smsg = (SMSG *) HeapAlloc( SystemHeap, 0, sizeof(SMSG) )) )
return 0;
if (!(queue = (MESSAGEQUEUE*)QUEUE_Lock( GetFastQueue16() ))) return 0;
if (!(destQ = (MESSAGEQUEUE*)QUEUE_Lock( hDestQueue )))
@ -671,7 +677,13 @@ static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND hwnd, UINT msg,
if (THREAD_IsWin16(THREAD_Current()) && THREAD_IsWin16(destQ->thdb) )
DirectedYield16( destQ->thdb->teb.htask16 );
QUEUE_WaitBits( QS_SMRESULT );
if (QUEUE_WaitBits( QS_SMRESULT, timeout ) == 0)
{
/* return with timeout */
SetLastError( 0 );
retVal = 0;
break;
}
if (! (smsg->flags & SMSG_HAVE_RESULT) )
{
@ -681,8 +693,8 @@ static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND hwnd, UINT msg,
}
else
{
lResult = smsg->lResult;
TRACE(sendmsg,"smResult = %08x\n", (unsigned)lResult );
*pRes = smsg->lResult;
TRACE(sendmsg,"smResult = %08x\n", (unsigned)*pRes );
}
}
@ -717,19 +729,11 @@ static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND hwnd, UINT msg,
/* Note: the destination thread is in charge of removing the smsg from
the pending list */
/* sender thread is in charge of releasing smsg if it's not an
early reply */
if ( !(smsg->flags & SMSG_EARLY_REPLY) )
{
HeapFree(SystemHeap, 0, smsg);
}
else
{
/* In the case of an early reply, 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 responsability to released
smsg */
/* 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
responsability to released smsg */
EnterCriticalSection( &queue->cSection );
if (smsg->flags & SMSG_RECEIVED)
@ -738,13 +742,13 @@ static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND hwnd, UINT msg,
smsg->flags |= SMSG_RECEIVER_CLEANS;
LeaveCriticalSection( &queue->cSection );
}
QUEUE_Unlock( queue );
QUEUE_Unlock( destQ );
TRACE(sendmsg,"done!\n");
return lResult;
return retVal;
}
@ -772,15 +776,15 @@ BOOL WINAPI ReplyMessage( LRESULT result )
while ((smsg = queue->smWaiting) != 0)
{
senderQ = (MESSAGEQUEUE*)QUEUE_Lock( smsg->hSrcQueue );
if ( !senderQ )
goto ReplyMessageEnd;
/* if message has already been reply, continue the loop of receving
message */
if ( smsg->flags & SMSG_ALREADY_REPLIED )
goto ReplyMessageDone;
senderQ = (MESSAGEQUEUE*)QUEUE_Lock( smsg->hSrcQueue );
if ( !senderQ )
goto ReplyMessageDone;
/* if send message pending, processed it */
if( queue->wakeBits & QS_SENDMESSAGE )
{
@ -793,7 +797,7 @@ BOOL WINAPI ReplyMessage( LRESULT result )
}
if ( !smsg )
goto ReplyMessageDone;
goto ReplyMessageEnd;
smsg->lResult = result;
smsg->flags |= SMSG_ALREADY_REPLIED;
@ -805,12 +809,6 @@ BOOL WINAPI ReplyMessage( LRESULT result )
TRACE( sendmsg,"\trpm: smResult = %08lx\n", (long) result );
/* remove smsg from the waiting list, if it's not an early reply */
/* it is important to leave it in the waiting list if it's an early
reply, to be protected aginst multiple call to ReplyMessage() */
if ( !(smsg->flags & SMSG_EARLY_REPLY) )
QUEUE_RemoveSMSG( queue, SM_WAITING_LIST, smsg );
EnterCriticalSection(&senderQ->cSection);
smsg->flags |= SMSG_HAVE_RESULT;
@ -827,6 +825,30 @@ BOOL WINAPI ReplyMessage( LRESULT result )
ret = TRUE;
ReplyMessageDone:
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 );
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 happens when there is
an early reply or a timeout */
if ( smsg->flags & SMSG_RECEIVER_CLEANS )
{
TRACE( sendmsg,"Receiver cleans up!\n" );
HeapFree( SystemHeap, 0, smsg );
}
LeaveCriticalSection(&senderQ->cSection);
}
ReplyMessageEnd:
if ( senderQ )
QUEUE_Unlock( senderQ );
if ( queue )
@ -984,7 +1006,7 @@ static BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, DWORD first, DWORD last,
return FALSE;
}
msgQueue->wakeMask = mask;
QUEUE_WaitBits( mask );
QUEUE_WaitBits( mask, INFINITE );
QUEUE_Unlock( msgQueue );
}
@ -1352,84 +1374,6 @@ BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 message, WPARAM16 wParam,
return QUEUE_AddMsg( GetTaskQueue16(hTask), &msg, 0 );
}
/***********************************************************************
* SendMessage16 (USER.111)
*/
LRESULT WINAPI SendMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
LPARAM lParam)
{
WND * wndPtr;
WND **list, **ppWnd;
LRESULT ret;
#ifdef CONFIG_IPC
MSG16 DDE_msg = { hwnd, msg, wParam, lParam };
if (DDE_SendMessage(&DDE_msg)) return TRUE;
#endif /* CONFIG_IPC */
if (hwnd == HWND_BROADCAST)
{
if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
return TRUE;
TRACE(msg,"HWND_BROADCAST !\n");
for (ppWnd = list; *ppWnd; ppWnd++)
{
wndPtr = *ppWnd;
if (!IsWindow(wndPtr->hwndSelf)) continue;
if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
{
TRACE(msg,"BROADCAST Message to hWnd=%04x m=%04X w=%04lX l=%08lX !\n",
wndPtr->hwndSelf, msg, (DWORD)wParam, lParam);
SendMessage16( wndPtr->hwndSelf, msg, wParam, lParam );
}
}
HeapFree( SystemHeap, 0, list );
TRACE(msg,"End of HWND_BROADCAST !\n");
return TRUE;
}
if (HOOK_IsHooked( WH_CALLWNDPROC ))
{
LPCWPSTRUCT16 pmsg;
if ((pmsg = SEGPTR_NEW(CWPSTRUCT16)))
{
pmsg->hwnd = hwnd;
pmsg->message= msg;
pmsg->wParam = wParam;
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 (!(wndPtr = WIN_FindWndPtr( hwnd )))
{
WARN(msg, "invalid hwnd %04x\n", hwnd );
return 0;
}
if (QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))
return 0; /* Don't send anything if the task is dying */
SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
if (wndPtr->hmemTaskQ != GetFastQueue16())
ret = MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg,
wParam, lParam, 0 );
else
ret = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
hwnd, msg, wParam, lParam );
SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, ret );
return ret;
}
/************************************************************************
* MSG_CallWndProcHook32
*/
@ -1451,6 +1395,133 @@ static void MSG_CallWndProcHook( LPMSG pmsg, BOOL bUnicode )
pmsg->hwnd = cwp.hwnd;
}
/***********************************************************************
* MSG_SendMessage
*
* return values: 0 if timeout occurs
* 1 otherwise
*/
LRESULT MSG_SendMessage( HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam, DWORD timeout, WORD flags,
LRESULT *pRes)
{
WND * wndPtr;
WND **list, **ppWnd;
LRESULT ret = 1;
*pRes = 0;
if (hwnd == HWND_BROADCAST)
{
*pRes = 1;
if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
return 1;
TRACE(msg,"HWND_BROADCAST !\n");
for (ppWnd = list; *ppWnd; ppWnd++)
{
wndPtr = *ppWnd;
if (!IsWindow(wndPtr->hwndSelf)) continue;
if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
{
TRACE(msg,"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);
}
}
HeapFree( SystemHeap, 0, list );
TRACE(msg,"End of HWND_BROADCAST !\n");
return 1;
}
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
{
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 (!(wndPtr = WIN_FindWndPtr( hwnd )))
{
WARN(msg, "invalid hwnd %04x\n", hwnd );
return 0;
}
if (QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))
return 0; /* Don't send anything if the task is dying */
if (flags & SMSG_WIN32)
SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wParam, lParam );
else
SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
if (wndPtr->hmemTaskQ != GetFastQueue16())
ret = MSG_SendMessageInterThread( wndPtr->hmemTaskQ, hwnd, msg,
wParam, lParam, timeout, flags, pRes );
else
{
/* Call the right CallWindowProc flavor */
if (flags & SMSG_UNICODE)
*pRes = CallWindowProcW( (WNDPROC)wndPtr->winproc,
hwnd, msg, wParam, lParam );
else if (flags & SMSG_WIN32)
*pRes = CallWindowProcA( (WNDPROC)wndPtr->winproc,
hwnd, msg, wParam, lParam );
else
*pRes = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
(HWND16) hwnd, (UINT16) msg,
(WPARAM16) wParam, lParam );
}
if (flags & SMSG_WIN32)
SPY_ExitMessage( SPY_RESULT_OK, hwnd, msg, ret );
else
SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, ret );
return ret;
}
/***********************************************************************
* SendMessage16 (USER.111)
*/
LRESULT WINAPI SendMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
LPARAM lParam)
{
LRESULT res;
#ifdef CONFIG_IPC
MSG16 DDE_msg = { hwnd, msg, wParam, lParam };
if (DDE_SendMessage(&DDE_msg)) return TRUE;
#endif /* CONFIG_IPC */
MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, 0, &res);
return res;
}
/**********************************************************************
* PostThreadMessage32A (USER32.422)
*
@ -1499,49 +1570,13 @@ BOOL WINAPI PostThreadMessageW(DWORD idThread , UINT message,
*/
LRESULT WINAPI SendMessageA( HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam )
{
WND * wndPtr;
WND **list, **ppWnd;
LRESULT ret;
if (hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST)
{
if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
return TRUE;
for (ppWnd = list; *ppWnd; ppWnd++)
{
wndPtr = *ppWnd;
if (!IsWindow(wndPtr->hwndSelf)) continue;
if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
SendMessageA( wndPtr->hwndSelf, msg, wParam, lParam );
}
HeapFree( SystemHeap, 0, list );
return TRUE;
}
LRESULT res;
if (HOOK_IsHooked( WH_CALLWNDPROC ))
MSG_CallWndProcHook( (LPMSG)&hwnd, FALSE);
MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE,
SMSG_WIN32, &res);
if (!(wndPtr = WIN_FindWndPtr( hwnd )))
{
WARN(msg, "invalid hwnd %08x\n", hwnd );
return 0;
}
if (QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))
return 0; /* Don't send anything if the task is dying */
SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wParam, lParam );
if (wndPtr->hmemTaskQ != GetFastQueue16())
ret = MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam,
SMSG_WIN32 );
else
ret = CallWindowProcA( (WNDPROC)wndPtr->winproc,
hwnd, msg, wParam, lParam );
SPY_ExitMessage( SPY_RESULT_OK, hwnd, msg, ret );
return ret;
return res;
}
@ -1572,47 +1607,12 @@ LRESULT WINAPI SendMessageW(
WPARAM wParam, /* message parameter */
LPARAM lParam /* additional message parameter */
) {
WND * wndPtr;
WND **list, **ppWnd;
LRESULT ret;
LRESULT res;
if (hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST)
{
if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
return TRUE;
for (ppWnd = list; *ppWnd; ppWnd++)
{
wndPtr = *ppWnd;
if (!IsWindow(wndPtr->hwndSelf)) continue;
if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
SendMessageW( wndPtr->hwndSelf, msg, wParam, lParam );
}
HeapFree( SystemHeap, 0, list );
return TRUE;
}
MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE,
SMSG_WIN32 | SMSG_UNICODE, &res);
if (HOOK_IsHooked( WH_CALLWNDPROC ))
MSG_CallWndProcHook( (LPMSG)&hwnd, TRUE);
if (!(wndPtr = WIN_FindWndPtr( hwnd )))
{
WARN(msg, "invalid hwnd %08x\n", hwnd );
return 0;
}
if (QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))
return 0; /* Don't send anything if the task is dying */
SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wParam, lParam );
if (wndPtr->hmemTaskQ != GetFastQueue16())
ret = MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam,
SMSG_WIN32 | SMSG_UNICODE );
else
ret = CallWindowProcW( (WNDPROC)wndPtr->winproc,
hwnd, msg, wParam, lParam );
SPY_ExitMessage( SPY_RESULT_OK, hwnd, msg, ret );
return ret;
return res;
}
@ -1623,32 +1623,54 @@ LRESULT WINAPI SendMessageTimeout16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
LPARAM lParam, UINT16 flags,
UINT16 timeout, LPWORD resultp)
{
FIXME(sendmsg, "(...): semistub\n");
return SendMessage16 (hwnd, msg, wParam, lParam);
LRESULT ret;
LRESULT msgRet;
/* FIXME: need support for SMTO_BLOCK */
ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, 0, &msgRet);
*resultp = (WORD) msgRet;
return ret;
}
/***********************************************************************
* SendMessageTimeout32A (USER32.457)
* SendMessageTimeoutA (USER32.457)
*/
LRESULT WINAPI SendMessageTimeoutA( HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam, UINT flags,
UINT timeout, LPDWORD resultp)
{
FIXME(sendmsg, "(...): semistub\n");
return SendMessageA (hwnd, msg, wParam, lParam);
LRESULT ret;
LRESULT msgRet;
/* FIXME: need support for SMTO_BLOCK */
ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, SMSG_WIN32,
&msgRet);
*resultp = (DWORD) msgRet;
return ret;
}
/***********************************************************************
* SendMessageTimeout32W (USER32.458)
* SendMessageTimeoutW (USER32.458)
*/
LRESULT WINAPI SendMessageTimeoutW( HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam, UINT flags,
UINT timeout, LPDWORD resultp)
{
FIXME(sendmsg, "(...): semistub\n");
return SendMessageW (hwnd, msg, wParam, lParam);
LRESULT ret;
LRESULT msgRet;
/* FIXME: need support for SMTO_BLOCK */
ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout,
SMSG_WIN32 | SMSG_UNICODE, &msgRet);
*resultp = (DWORD) msgRet;
return ret;
}
@ -1671,7 +1693,7 @@ LRESULT WINAPI SendMessageTimeoutW( HWND hwnd, UINT msg, WPARAM wParam,
*/
void WINAPI WaitMessage( void )
{
QUEUE_WaitBits( QS_ALLINPUT );
QUEUE_WaitBits( QS_ALLINPUT, INFINITE );
}
/***********************************************************************

View File

@ -611,21 +611,6 @@ MESSAGEQUEUE *QUEUE_GetSysQueue(void)
}
/***********************************************************************
* QUEUE_Wait
*/
static void QUEUE_Wait( DWORD wait_mask )
{
if ( THREAD_IsWin16( THREAD_Current() ) )
WaitEvent16( 0 );
else
{
TRACE(msg, "current task is 32-bit, calling SYNC_DoWait\n");
MsgWaitForMultipleObjects( 0, NULL, FALSE, INFINITE, wait_mask );
}
}
/***********************************************************************
* QUEUE_SetWakeBit
*
@ -669,23 +654,31 @@ void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit )
* QUEUE_WaitBits
*
* See "Windows Internals", p.447
*
* return values:
* 0 if exit with timeout
* 1 otherwise
*/
void QUEUE_WaitBits( WORD bits )
int QUEUE_WaitBits( WORD bits, DWORD timeout )
{
MESSAGEQUEUE *queue;
DWORD curTime = 0;
TRACE(msg,"q %04x waiting for %04x\n", GetFastQueue16(), bits);
if ( THREAD_IsWin16( THREAD_Current() ) && (timeout != INFINITE) )
curTime = GetTickCount();
if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
for (;;)
{
if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return;
if (queue->changeBits & bits)
{
/* One of the bits is set; we can return */
queue->wakeMask = 0;
QUEUE_Unlock( queue );
return;
return 1;
}
if (queue->wakeBits & QS_SENDMESSAGE)
{
@ -693,24 +686,40 @@ void QUEUE_WaitBits( WORD bits )
queue->wakeMask = 0;
QUEUE_ReceiveMessage( queue );
QUEUE_Unlock( queue );
continue; /* nested sm crux */
}
queue->wakeMask = bits | QS_SENDMESSAGE;
if(queue->changeBits & bits)
{
QUEUE_Unlock( queue );
continue;
}
TRACE(msg,"%04x) wakeMask is %04x, waiting\n", queue->self, queue->wakeMask);
QUEUE_Wait( queue->wakeMask );
if ( !THREAD_IsWin16( THREAD_Current() ) )
{
/* win32 thread, use WaitForMultipleObjects */
MsgWaitForMultipleObjects( 0, NULL, FALSE, timeout, queue->wakeMask );
}
else
{
if ( timeout == INFINITE )
WaitEvent16( 0 ); /* win 16 thread, use WaitEvent */
else
{
/* check for timeout, then give control to other tasks */
if (GetTickCount() - curTime > timeout)
{
QUEUE_Unlock( queue );
return 0; /* exit with timeout */
}
Yield16();
}
}
}
}
/***********************************************************************
@ -919,54 +928,11 @@ void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue )
}
else WARN(sendmsg, "\trcm: bad hWnd\n");
/* sometimes when we got early reply, the receiver is in charge of
freeing up memory associated with smsg */
/* when there is an early reply the sender will not release smsg
before SMSG_RECEIVED is set */
if ( smsg->flags & SMSG_EARLY_REPLY )
{
/* remove smsg from the waiting list */
QUEUE_RemoveSMSG( queue, SM_WAITING_LIST, smsg );
/* make thread safe when accessing SMSG_SENT_REPLY and
SMSG_RECEIVER_CLEANS_UP. Those fleags are used by both thread,
the sender and receiver, to find out which thread should released
smsg structure. The critical section of the sender queue is used. */
senderQ = (MESSAGEQUEUE*)QUEUE_Lock( smsg->hSrcQueue );
/* synchronize with the sender */
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 happens when there is
an early reply */
if ( smsg->flags & SMSG_RECEIVER_CLEANS )
{
TRACE( sendmsg,"Receiver cleans up!\n" );
HeapFree( SystemHeap, 0, smsg );
}
/* release lock */
if (senderQ)
{
LeaveCriticalSection( &senderQ->cSection );
QUEUE_Unlock( senderQ );
}
}
else
{
/* no early reply, so do it now */
/* set SMSG_SENDING_REPLY flag to tell ReplyMessage16, it's not
an early reply */
smsg->flags |= SMSG_SENDING_REPLY;
ReplyMessage( result );
}
TRACE( sendmsg,"done! \n" );
}