Implemented SendMessageTimeout() functions.
This commit is contained in:
parent
ebe76b73a9
commit
bae5552a14
|
@ -152,7 +152,7 @@ extern MESSAGEQUEUE *QUEUE_GetSysQueue(void);
|
||||||
extern void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit );
|
extern void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit );
|
||||||
extern void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit );
|
extern void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit );
|
||||||
extern void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue );
|
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_IncPaintCount( HQUEUE16 hQueue );
|
||||||
extern void QUEUE_DecPaintCount( HQUEUE16 hQueue );
|
extern void QUEUE_DecPaintCount( HQUEUE16 hQueue );
|
||||||
extern void QUEUE_IncTimerCount( HQUEUE16 hQueue );
|
extern void QUEUE_IncTimerCount( HQUEUE16 hQueue );
|
||||||
|
|
|
@ -44,7 +44,6 @@ DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
|
||||||
|
|
||||||
static UINT doubleClickSpeed = 452;
|
static UINT doubleClickSpeed = 452;
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* MSG_CheckFilter
|
* MSG_CheckFilter
|
||||||
*/
|
*/
|
||||||
|
@ -617,16 +616,24 @@ UINT WINAPI GetDoubleClickTime(void)
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* MSG_SendMessage
|
* MSG_SendMessageInterThread
|
||||||
*
|
*
|
||||||
* Implementation of an inter-task SendMessage.
|
* 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,
|
static LRESULT MSG_SendMessageInterThread( HQUEUE16 hDestQueue,
|
||||||
WPARAM wParam, LPARAM lParam, WORD flags )
|
HWND hwnd, UINT msg,
|
||||||
|
WPARAM wParam, LPARAM lParam,
|
||||||
|
DWORD timeout, WORD flags,
|
||||||
|
LRESULT *pRes)
|
||||||
{
|
{
|
||||||
MESSAGEQUEUE *queue, *destQ;
|
MESSAGEQUEUE *queue, *destQ;
|
||||||
SMSG *smsg;
|
SMSG *smsg;
|
||||||
LRESULT lResult = 0;
|
LRESULT retVal = 1;
|
||||||
|
|
||||||
|
*pRes = 0;
|
||||||
|
|
||||||
if (IsTaskLocked16() || !IsWindow(hwnd))
|
if (IsTaskLocked16() || !IsWindow(hwnd))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -634,7 +641,6 @@ static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND hwnd, UINT msg,
|
||||||
/* create a SMSG structure to hold SendMessage() parameters */
|
/* create a SMSG structure to hold SendMessage() parameters */
|
||||||
if (! (smsg = (SMSG *) HeapAlloc( SystemHeap, 0, sizeof(SMSG) )) )
|
if (! (smsg = (SMSG *) HeapAlloc( SystemHeap, 0, sizeof(SMSG) )) )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(queue = (MESSAGEQUEUE*)QUEUE_Lock( GetFastQueue16() ))) return 0;
|
if (!(queue = (MESSAGEQUEUE*)QUEUE_Lock( GetFastQueue16() ))) return 0;
|
||||||
|
|
||||||
if (!(destQ = (MESSAGEQUEUE*)QUEUE_Lock( hDestQueue )))
|
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) )
|
if (THREAD_IsWin16(THREAD_Current()) && THREAD_IsWin16(destQ->thdb) )
|
||||||
DirectedYield16( destQ->thdb->teb.htask16 );
|
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) )
|
if (! (smsg->flags & SMSG_HAVE_RESULT) )
|
||||||
{
|
{
|
||||||
|
@ -681,8 +693,8 @@ static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND hwnd, UINT msg,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lResult = smsg->lResult;
|
*pRes = smsg->lResult;
|
||||||
TRACE(sendmsg,"smResult = %08x\n", (unsigned)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
|
/* Note: the destination thread is in charge of removing the smsg from
|
||||||
the pending list */
|
the pending list */
|
||||||
|
|
||||||
/* sender thread is in charge of releasing smsg if it's not an
|
/* In the case of an early reply (or a timeout), sender thread will
|
||||||
early reply */
|
released the smsg structure if the receiver thread is done
|
||||||
if ( !(smsg->flags & SMSG_EARLY_REPLY) )
|
(SMSG_RECEIVED set). If the receiver thread isn't done,
|
||||||
{
|
SMSG_RECEIVER_CLEANS_UP flag is set, and it will be the receiver
|
||||||
HeapFree(SystemHeap, 0, smsg);
|
responsability to released 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 */
|
|
||||||
EnterCriticalSection( &queue->cSection );
|
EnterCriticalSection( &queue->cSection );
|
||||||
|
|
||||||
if (smsg->flags & SMSG_RECEIVED)
|
if (smsg->flags & SMSG_RECEIVED)
|
||||||
|
@ -738,13 +742,13 @@ static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND hwnd, UINT msg,
|
||||||
smsg->flags |= SMSG_RECEIVER_CLEANS;
|
smsg->flags |= SMSG_RECEIVER_CLEANS;
|
||||||
|
|
||||||
LeaveCriticalSection( &queue->cSection );
|
LeaveCriticalSection( &queue->cSection );
|
||||||
}
|
|
||||||
|
|
||||||
QUEUE_Unlock( queue );
|
QUEUE_Unlock( queue );
|
||||||
QUEUE_Unlock( destQ );
|
QUEUE_Unlock( destQ );
|
||||||
|
|
||||||
TRACE(sendmsg,"done!\n");
|
TRACE(sendmsg,"done!\n");
|
||||||
return lResult;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -772,15 +776,15 @@ BOOL WINAPI ReplyMessage( LRESULT result )
|
||||||
|
|
||||||
while ((smsg = queue->smWaiting) != 0)
|
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
|
/* if message has already been reply, continue the loop of receving
|
||||||
message */
|
message */
|
||||||
if ( smsg->flags & SMSG_ALREADY_REPLIED )
|
if ( smsg->flags & SMSG_ALREADY_REPLIED )
|
||||||
goto ReplyMessageDone;
|
goto ReplyMessageDone;
|
||||||
|
|
||||||
senderQ = (MESSAGEQUEUE*)QUEUE_Lock( smsg->hSrcQueue );
|
|
||||||
if ( !senderQ )
|
|
||||||
goto ReplyMessageDone;
|
|
||||||
|
|
||||||
/* if send message pending, processed it */
|
/* if send message pending, processed it */
|
||||||
if( queue->wakeBits & QS_SENDMESSAGE )
|
if( queue->wakeBits & QS_SENDMESSAGE )
|
||||||
{
|
{
|
||||||
|
@ -793,7 +797,7 @@ BOOL WINAPI ReplyMessage( LRESULT result )
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !smsg )
|
if ( !smsg )
|
||||||
goto ReplyMessageDone;
|
goto ReplyMessageEnd;
|
||||||
|
|
||||||
smsg->lResult = result;
|
smsg->lResult = result;
|
||||||
smsg->flags |= SMSG_ALREADY_REPLIED;
|
smsg->flags |= SMSG_ALREADY_REPLIED;
|
||||||
|
@ -805,12 +809,6 @@ BOOL WINAPI ReplyMessage( LRESULT result )
|
||||||
|
|
||||||
TRACE( sendmsg,"\trpm: smResult = %08lx\n", (long) 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);
|
EnterCriticalSection(&senderQ->cSection);
|
||||||
|
|
||||||
smsg->flags |= SMSG_HAVE_RESULT;
|
smsg->flags |= SMSG_HAVE_RESULT;
|
||||||
|
@ -827,6 +825,30 @@ BOOL WINAPI ReplyMessage( LRESULT result )
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
|
|
||||||
ReplyMessageDone:
|
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 )
|
if ( senderQ )
|
||||||
QUEUE_Unlock( senderQ );
|
QUEUE_Unlock( senderQ );
|
||||||
if ( queue )
|
if ( queue )
|
||||||
|
@ -984,7 +1006,7 @@ static BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, DWORD first, DWORD last,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
msgQueue->wakeMask = mask;
|
msgQueue->wakeMask = mask;
|
||||||
QUEUE_WaitBits( mask );
|
QUEUE_WaitBits( mask, INFINITE );
|
||||||
QUEUE_Unlock( msgQueue );
|
QUEUE_Unlock( msgQueue );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1352,84 +1374,6 @@ BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 message, WPARAM16 wParam,
|
||||||
return QUEUE_AddMsg( GetTaskQueue16(hTask), &msg, 0 );
|
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
|
* MSG_CallWndProcHook32
|
||||||
*/
|
*/
|
||||||
|
@ -1451,6 +1395,133 @@ static void MSG_CallWndProcHook( LPMSG pmsg, BOOL bUnicode )
|
||||||
pmsg->hwnd = cwp.hwnd;
|
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)
|
* PostThreadMessage32A (USER32.422)
|
||||||
*
|
*
|
||||||
|
@ -1499,49 +1570,13 @@ BOOL WINAPI PostThreadMessageW(DWORD idThread , UINT message,
|
||||||
*/
|
*/
|
||||||
LRESULT WINAPI SendMessageA( HWND hwnd, UINT msg, WPARAM wParam,
|
LRESULT WINAPI SendMessageA( HWND hwnd, UINT msg, WPARAM wParam,
|
||||||
LPARAM lParam )
|
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;
|
LRESULT res;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HOOK_IsHooked( WH_CALLWNDPROC ))
|
MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE,
|
||||||
MSG_CallWndProcHook( (LPMSG)&hwnd, FALSE);
|
SMSG_WIN32, &res);
|
||||||
|
|
||||||
if (!(wndPtr = WIN_FindWndPtr( hwnd )))
|
return res;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1572,47 +1607,12 @@ LRESULT WINAPI SendMessageW(
|
||||||
WPARAM wParam, /* message parameter */
|
WPARAM wParam, /* message parameter */
|
||||||
LPARAM lParam /* additional message parameter */
|
LPARAM lParam /* additional message parameter */
|
||||||
) {
|
) {
|
||||||
WND * wndPtr;
|
LRESULT res;
|
||||||
WND **list, **ppWnd;
|
|
||||||
LRESULT ret;
|
|
||||||
|
|
||||||
if (hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST)
|
MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE,
|
||||||
{
|
SMSG_WIN32 | SMSG_UNICODE, &res);
|
||||||
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 ))
|
return res;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1623,32 +1623,54 @@ LRESULT WINAPI SendMessageTimeout16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
|
||||||
LPARAM lParam, UINT16 flags,
|
LPARAM lParam, UINT16 flags,
|
||||||
UINT16 timeout, LPWORD resultp)
|
UINT16 timeout, LPWORD resultp)
|
||||||
{
|
{
|
||||||
FIXME(sendmsg, "(...): semistub\n");
|
LRESULT ret;
|
||||||
return SendMessage16 (hwnd, msg, wParam, lParam);
|
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,
|
LRESULT WINAPI SendMessageTimeoutA( HWND hwnd, UINT msg, WPARAM wParam,
|
||||||
LPARAM lParam, UINT flags,
|
LPARAM lParam, UINT flags,
|
||||||
UINT timeout, LPDWORD resultp)
|
UINT timeout, LPDWORD resultp)
|
||||||
{
|
{
|
||||||
FIXME(sendmsg, "(...): semistub\n");
|
LRESULT ret;
|
||||||
return SendMessageA (hwnd, msg, wParam, lParam);
|
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,
|
LRESULT WINAPI SendMessageTimeoutW( HWND hwnd, UINT msg, WPARAM wParam,
|
||||||
LPARAM lParam, UINT flags,
|
LPARAM lParam, UINT flags,
|
||||||
UINT timeout, LPDWORD resultp)
|
UINT timeout, LPDWORD resultp)
|
||||||
{
|
{
|
||||||
FIXME(sendmsg, "(...): semistub\n");
|
LRESULT ret;
|
||||||
return SendMessageW (hwnd, msg, wParam, lParam);
|
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 )
|
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
|
* QUEUE_SetWakeBit
|
||||||
*
|
*
|
||||||
|
@ -669,23 +654,31 @@ void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit )
|
||||||
* QUEUE_WaitBits
|
* QUEUE_WaitBits
|
||||||
*
|
*
|
||||||
* See "Windows Internals", p.447
|
* 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;
|
MESSAGEQUEUE *queue;
|
||||||
|
DWORD curTime = 0;
|
||||||
|
|
||||||
TRACE(msg,"q %04x waiting for %04x\n", GetFastQueue16(), bits);
|
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 (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return;
|
|
||||||
|
|
||||||
if (queue->changeBits & bits)
|
if (queue->changeBits & bits)
|
||||||
{
|
{
|
||||||
/* One of the bits is set; we can return */
|
/* One of the bits is set; we can return */
|
||||||
queue->wakeMask = 0;
|
queue->wakeMask = 0;
|
||||||
QUEUE_Unlock( queue );
|
QUEUE_Unlock( queue );
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
if (queue->wakeBits & QS_SENDMESSAGE)
|
if (queue->wakeBits & QS_SENDMESSAGE)
|
||||||
{
|
{
|
||||||
|
@ -693,24 +686,40 @@ void QUEUE_WaitBits( WORD bits )
|
||||||
|
|
||||||
queue->wakeMask = 0;
|
queue->wakeMask = 0;
|
||||||
QUEUE_ReceiveMessage( queue );
|
QUEUE_ReceiveMessage( queue );
|
||||||
QUEUE_Unlock( queue );
|
|
||||||
continue; /* nested sm crux */
|
continue; /* nested sm crux */
|
||||||
}
|
}
|
||||||
|
|
||||||
queue->wakeMask = bits | QS_SENDMESSAGE;
|
queue->wakeMask = bits | QS_SENDMESSAGE;
|
||||||
if(queue->changeBits & bits)
|
if(queue->changeBits & bits)
|
||||||
{
|
{
|
||||||
QUEUE_Unlock( queue );
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(msg,"%04x) wakeMask is %04x, waiting\n", queue->self, queue->wakeMask);
|
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 );
|
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");
|
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
|
/* set SMSG_SENDING_REPLY flag to tell ReplyMessage16, it's not
|
||||||
an early reply */
|
an early reply */
|
||||||
smsg->flags |= SMSG_SENDING_REPLY;
|
smsg->flags |= SMSG_SENDING_REPLY;
|
||||||
ReplyMessage( result );
|
ReplyMessage( result );
|
||||||
}
|
|
||||||
|
|
||||||
TRACE( sendmsg,"done! \n" );
|
TRACE( sendmsg,"done! \n" );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue