diff --git a/include/queue.h b/include/queue.h index f8f375e7359..6cbdaadd539 100644 --- a/include/queue.h +++ b/include/queue.h @@ -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 ); diff --git a/windows/message.c b/windows/message.c index b91b4e3d94b..6e3880886ac 100644 --- a/windows/message.c +++ b/windows/message.c @@ -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 ); } /*********************************************************************** diff --git a/windows/queue.c b/windows/queue.c index 7da4e2f468b..c2a4da22834 100644 --- a/windows/queue.c +++ b/windows/queue.c @@ -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" ); }