Skip to content
Snippets Groups Projects
Commit bae5552a authored by Stephane Lussier's avatar Stephane Lussier Committed by Alexandre Julliard
Browse files

Implemented SendMessageTimeout() functions.

parent ebe76b73
No related branches found
No related tags found
No related merge requests found
......@@ -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 );
......
......@@ -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,26 +1374,50 @@ BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 message, WPARAM16 wParam,
return QUEUE_AddMsg( GetTaskQueue16(hTask), &msg, 0 );
}
/************************************************************************
* MSG_CallWndProcHook32
*/
static void MSG_CallWndProcHook( LPMSG pmsg, BOOL bUnicode )
{
CWPSTRUCT cwp;
cwp.lParam = pmsg->lParam;
cwp.wParam = pmsg->wParam;
cwp.message = pmsg->message;
cwp.hwnd = pmsg->hwnd;
if (bUnicode) HOOK_CallHooksW(WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp);
else HOOK_CallHooksA( WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp );
pmsg->lParam = cwp.lParam;
pmsg->wParam = cwp.wParam;
pmsg->message = cwp.message;
pmsg->hwnd = cwp.hwnd;
}
/***********************************************************************
* SendMessage16 (USER.111)
* MSG_SendMessage
*
* return values: 0 if timeout occurs
* 1 otherwise
*/
LRESULT WINAPI SendMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
LPARAM lParam)
LRESULT MSG_SendMessage( HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam, DWORD timeout, WORD flags,
LRESULT *pRes)
{
WND * wndPtr;
WND **list, **ppWnd;
LRESULT ret;
LRESULT ret = 1;
#ifdef CONFIG_IPC
MSG16 DDE_msg = { hwnd, msg, wParam, lParam };
if (DDE_SendMessage(&DDE_msg)) return TRUE;
#endif /* CONFIG_IPC */
*pRes = 0;
if (hwnd == HWND_BROADCAST)
{
*pRes = 1;
if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
return TRUE;
return 1;
TRACE(msg,"HWND_BROADCAST !\n");
for (ppWnd = list; *ppWnd; ppWnd++)
{
......@@ -1381,23 +1427,30 @@ LRESULT WINAPI SendMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
{
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 );
MSG_SendMessage( wndPtr->hwndSelf, msg, wParam, lParam,
timeout, flags, pRes);
}
}
HeapFree( SystemHeap, 0, list );
TRACE(msg,"End of HWND_BROADCAST !\n");
return TRUE;
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;
pmsg->message= msg;
pmsg->wParam = wParam;
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) );
......@@ -1408,6 +1461,7 @@ LRESULT WINAPI SendMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
SEGPTR_FREE( pmsg );
}
}
}
if (!(wndPtr = WIN_FindWndPtr( hwnd )))
{
......@@ -1417,40 +1471,57 @@ LRESULT WINAPI SendMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
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_SendMessage( wndPtr->hmemTaskQ, hwnd, msg,
wParam, lParam, 0 );
ret = MSG_SendMessageInterThread( wndPtr->hmemTaskQ, hwnd, msg,
wParam, lParam, timeout, flags, pRes );
else
ret = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
{
/* 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;
}
/************************************************************************
* MSG_CallWndProcHook32
/***********************************************************************
* SendMessage16 (USER.111)
*/
static void MSG_CallWndProcHook( LPMSG pmsg, BOOL bUnicode )
LRESULT WINAPI SendMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
LPARAM lParam)
{
CWPSTRUCT cwp;
cwp.lParam = pmsg->lParam;
cwp.wParam = pmsg->wParam;
cwp.message = pmsg->message;
cwp.hwnd = pmsg->hwnd;
LRESULT res;
#ifdef CONFIG_IPC
MSG16 DDE_msg = { hwnd, msg, wParam, lParam };
if (DDE_SendMessage(&DDE_msg)) return TRUE;
#endif /* CONFIG_IPC */
if (bUnicode) HOOK_CallHooksW(WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp);
else HOOK_CallHooksA( WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp );
MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, 0, &res);
pmsg->lParam = cwp.lParam;
pmsg->wParam = cwp.wParam;
pmsg->message = cwp.message;
pmsg->hwnd = cwp.hwnd;
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);
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 );
MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE,
SMSG_WIN32, &res);
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;
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;
}
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 */
LRESULT res;
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 );
MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE,
SMSG_WIN32 | SMSG_UNICODE, &res);
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 );
}
/***********************************************************************
......
......@@ -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" );
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment