- New implementation of SendMessage, ReceiveMessage, ReplyMessage functions
to support thread-safeness, and nested SendMessage. - Addition of ReplyMessage32.
This commit is contained in:
parent
4aaf65e6b4
commit
2c86dab53a
@ -22,11 +22,43 @@ typedef struct tagQMSG
|
|||||||
struct tagQMSG *prevMsg;
|
struct tagQMSG *prevMsg;
|
||||||
} QMSG;
|
} QMSG;
|
||||||
|
|
||||||
typedef struct
|
|
||||||
|
typedef struct tagSMSG
|
||||||
{
|
{
|
||||||
LRESULT lResult;
|
struct tagSMSG *nextProcessing; /* next SMSG in the processing list */
|
||||||
BOOL16 bPending;
|
struct tagSMSG *nextPending; /* next SMSG in the pending list */
|
||||||
} QSMCTRL;
|
struct tagSMSG *nextWaiting; /* next SMSG in the waiting list */
|
||||||
|
|
||||||
|
HQUEUE16 hSrcQueue; /* sending Queue, (NULL if it didn't wait) */
|
||||||
|
HQUEUE16 hDstQueue; /* destination Queue */
|
||||||
|
|
||||||
|
HWND32 hWnd; /* destinantion window */
|
||||||
|
UINT32 msg; /* message sent */
|
||||||
|
WPARAM32 wParam; /* wParam of the sent message */
|
||||||
|
LPARAM lParam; /* lParam of the sent message */
|
||||||
|
|
||||||
|
LRESULT lResult; /* result of SendMessage */
|
||||||
|
WORD flags; /* see below SMSG_XXXX */
|
||||||
|
} SMSG;
|
||||||
|
|
||||||
|
|
||||||
|
/* SMSG -> flags values */
|
||||||
|
/* set when lResult contains a good value */
|
||||||
|
#define SMSG_HAVE_RESULT 0x0001
|
||||||
|
/* protection for multiple call to ReplyMessage16() */
|
||||||
|
#define SMSG_ALREADY_REPLIED 0x0002
|
||||||
|
/* use with EARLY_REPLY for forcing the receiver to clean SMSG */
|
||||||
|
#define SMSG_RECEIVER_CLEANS 0x0010
|
||||||
|
/* used with EARLY_REPLY to indicate to sender, receiver is done with SMSG */
|
||||||
|
#define SMSG_RECEIVED 0x0020
|
||||||
|
/* set in ReceiveMessage() to indicate it's not an early reply */
|
||||||
|
#define SMSG_SENDING_REPLY 0x0040
|
||||||
|
/* set when ReplyMessage16() is called by the application */
|
||||||
|
#define SMSG_EARLY_REPLY 0x0080
|
||||||
|
/* set when sender is Win32 thread */
|
||||||
|
#define SMSG_WIN32 0x1000
|
||||||
|
/* set when sender is a unnicode thread */
|
||||||
|
#define SMSG_UNICODE 0x2000
|
||||||
|
|
||||||
/* Per-queue data for the message queue
|
/* Per-queue data for the message queue
|
||||||
* Note that we currently only store the current values for
|
* Note that we currently only store the current values for
|
||||||
@ -55,8 +87,6 @@ typedef struct tagMESSAGEQUEUE
|
|||||||
|
|
||||||
DWORD magic; /* magic number should be QUEUE_MAGIC */
|
DWORD magic; /* magic number should be QUEUE_MAGIC */
|
||||||
DWORD lockCount; /* reference counter */
|
DWORD lockCount; /* reference counter */
|
||||||
|
|
||||||
WORD flags; /* Queue flags */
|
|
||||||
WORD wWinVersion; /* Expected Windows version */
|
WORD wWinVersion; /* Expected Windows version */
|
||||||
|
|
||||||
WORD msgCount; /* Number of waiting messages */
|
WORD msgCount; /* Number of waiting messages */
|
||||||
@ -76,19 +106,9 @@ typedef struct tagMESSAGEQUEUE
|
|||||||
DWORD GetMessagePosVal; /* Value for GetMessagePos */
|
DWORD GetMessagePosVal; /* Value for GetMessagePos */
|
||||||
DWORD GetMessageExtraInfoVal; /* Value for GetMessageExtraInfo */
|
DWORD GetMessageExtraInfoVal; /* Value for GetMessageExtraInfo */
|
||||||
|
|
||||||
HQUEUE16 InSendMessageHandle; /* Queue of task that sent a message */
|
SMSG* smWaiting; /* SendMessage waiting for reply */
|
||||||
HTASK16 hSendingTask; /* Handle of task that sent a message */
|
SMSG* smProcessing; /* SendMessage currently being processed */
|
||||||
HTASK16 hPrevSendingTask; /* Handle of previous sender */
|
SMSG* smPending; /* SendMessage waiting to be received */
|
||||||
|
|
||||||
HWND32 hWnd32; /* Send message arguments */
|
|
||||||
UINT32 msg32;
|
|
||||||
WPARAM32 wParam32;
|
|
||||||
LPARAM lParam;
|
|
||||||
DWORD SendMessageReturn; /* Return value for SendMessage */
|
|
||||||
|
|
||||||
QSMCTRL* smResultInit; /* SendMesage result pointers */
|
|
||||||
QSMCTRL* smResultCurrent;
|
|
||||||
QSMCTRL* smResult;
|
|
||||||
|
|
||||||
HANDLE16 hCurHook; /* Current hook */
|
HANDLE16 hCurHook; /* Current hook */
|
||||||
HANDLE16 hooks[WH_NB_HOOKS]; /* Task hooks list */
|
HANDLE16 hooks[WH_NB_HOOKS]; /* Task hooks list */
|
||||||
@ -100,11 +120,11 @@ typedef struct tagMESSAGEQUEUE
|
|||||||
|
|
||||||
/* Extra (undocumented) queue wake bits - see "Undoc. Windows" */
|
/* Extra (undocumented) queue wake bits - see "Undoc. Windows" */
|
||||||
#define QS_SMRESULT 0x8000 /* Queue has a SendMessage() result */
|
#define QS_SMRESULT 0x8000 /* Queue has a SendMessage() result */
|
||||||
#define QS_SMPARAMSFREE 0x4000 /* SendMessage() parameters are available */
|
|
||||||
|
|
||||||
/* Queue flags */
|
/* Types of SMSG stack */
|
||||||
#define QUEUE_SM_WIN32 0x0002 /* Currently sent message is Win32 */
|
#define SM_PROCESSING_LIST 1 /* list of SM currently being processed */
|
||||||
#define QUEUE_SM_UNICODE 0x0004 /* Currently sent message is Unicode */
|
#define SM_PENDING_LIST 2 /* list of SM wating to be received */
|
||||||
|
#define SM_WAITING_LIST 3 /* list of SM waiting for reply */
|
||||||
|
|
||||||
#define QUEUE_MAGIC 0xD46E80AF
|
#define QUEUE_MAGIC 0xD46E80AF
|
||||||
|
|
||||||
@ -144,7 +164,8 @@ extern BOOL32 QUEUE_AddMsg( HQUEUE16 hQueue, MSG32 * msg, DWORD extraInfo );
|
|||||||
extern QMSG* QUEUE_FindMsg( MESSAGEQUEUE * msgQueue, HWND32 hwnd,
|
extern QMSG* QUEUE_FindMsg( MESSAGEQUEUE * msgQueue, HWND32 hwnd,
|
||||||
int first, int last );
|
int first, int last );
|
||||||
extern void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, QMSG *qmsg );
|
extern void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, QMSG *qmsg );
|
||||||
extern void QUEUE_FlushMessages(HQUEUE16);
|
extern SMSG *QUEUE_RemoveSMSG( MESSAGEQUEUE *queue, int list, SMSG *smsg );
|
||||||
|
extern BOOL32 QUEUE_AddSMSG( MESSAGEQUEUE *queue, int list, SMSG *smsg );
|
||||||
extern void hardware_event( WORD message, WORD wParam, LONG lParam,
|
extern void hardware_event( WORD message, WORD wParam, LONG lParam,
|
||||||
int xPos, int yPos, DWORD time, DWORD extraInfo );
|
int xPos, int yPos, DWORD time, DWORD extraInfo );
|
||||||
|
|
||||||
|
@ -445,7 +445,7 @@ init MAIN_UserInit
|
|||||||
441 stdcall RemoveMenu(long long long) RemoveMenu32
|
441 stdcall RemoveMenu(long long long) RemoveMenu32
|
||||||
442 stdcall RemovePropA(long str) RemoveProp32A
|
442 stdcall RemovePropA(long str) RemoveProp32A
|
||||||
443 stdcall RemovePropW(long wstr) RemoveProp32W
|
443 stdcall RemovePropW(long wstr) RemoveProp32W
|
||||||
444 stub ReplyMessage
|
444 stdcall ReplyMessage(long) ReplyMessage32
|
||||||
445 stub ResetDisplay
|
445 stub ResetDisplay
|
||||||
446 stdcall ReuseDDElParam(long long long long long) ReuseDDElParam
|
446 stdcall ReuseDDElParam(long long long long long) ReuseDDElParam
|
||||||
447 stdcall ScreenToClient(long ptr) ScreenToClient32
|
447 stdcall ScreenToClient(long ptr) ScreenToClient32
|
||||||
|
@ -43,7 +43,7 @@ extern HQUEUE16 hCursorQueue; /* queue.c */
|
|||||||
DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
|
DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
|
||||||
|
|
||||||
static UINT32 doubleClickSpeed = 452;
|
static UINT32 doubleClickSpeed = 452;
|
||||||
static INT32 debugSMRL = 0; /* intertask SendMessage() recursion level */
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* MSG_CheckFilter
|
* MSG_CheckFilter
|
||||||
@ -621,16 +621,20 @@ UINT32 WINAPI GetDoubleClickTime32(void)
|
|||||||
*
|
*
|
||||||
* Implementation of an inter-task SendMessage.
|
* Implementation of an inter-task SendMessage.
|
||||||
*/
|
*/
|
||||||
static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND16 hwnd, UINT16 msg,
|
static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND32 hwnd, UINT32 msg,
|
||||||
WPARAM32 wParam, LPARAM lParam, WORD flags )
|
WPARAM32 wParam, LPARAM lParam, WORD flags )
|
||||||
{
|
{
|
||||||
INT32 prevSMRL = debugSMRL;
|
|
||||||
QSMCTRL qCtrl = { 0, 1};
|
|
||||||
MESSAGEQUEUE *queue, *destQ;
|
MESSAGEQUEUE *queue, *destQ;
|
||||||
|
SMSG *smsg;
|
||||||
|
LRESULT lResult = 0;
|
||||||
|
|
||||||
if (IsTaskLocked() || !IsWindow32(hwnd))
|
if (IsTaskLocked() || !IsWindow32(hwnd))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* create a SMSG structure to hold SendMessage() parameters */
|
||||||
|
if (! (smsg = (SMSG *) HeapAlloc( SystemHeap, 0, sizeof(SMSG) )) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!(queue = (MESSAGEQUEUE*)QUEUE_Lock( GetFastQueue() ))) return 0;
|
if (!(queue = (MESSAGEQUEUE*)QUEUE_Lock( GetFastQueue() ))) return 0;
|
||||||
|
|
||||||
if (!(destQ = (MESSAGEQUEUE*)QUEUE_Lock( hDestQueue )))
|
if (!(destQ = (MESSAGEQUEUE*)QUEUE_Lock( hDestQueue )))
|
||||||
@ -639,66 +643,84 @@ static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND16 hwnd, UINT16 msg,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
debugSMRL+=4;
|
TRACE(sendmsg,"SM: %s [%04x] (%04x -> %04x)\n",
|
||||||
TRACE(sendmsg,"%*sSM: %s [%04x] (%04x -> %04x)\n",
|
SPY_GetMsgName(msg), msg, queue->self, hDestQueue );
|
||||||
prevSMRL, "", SPY_GetMsgName(msg), msg, queue->self, hDestQueue );
|
|
||||||
|
|
||||||
if( !(queue->wakeBits & QS_SMPARAMSFREE) )
|
/* fill up SMSG structure */
|
||||||
{
|
smsg->hWnd = hwnd;
|
||||||
TRACE(sendmsg,"\tIntertask SendMessage: sleeping since unreplied SendMessage pending\n");
|
smsg->msg = msg;
|
||||||
QUEUE_WaitBits( QS_SMPARAMSFREE );
|
smsg->wParam = wParam;
|
||||||
}
|
smsg->lParam = lParam;
|
||||||
|
|
||||||
/* resume sending */
|
smsg->lResult = 0;
|
||||||
queue->hWnd32 = hwnd;
|
smsg->hSrcQueue = GetFastQueue();
|
||||||
queue->msg32 = msg;
|
smsg->hDstQueue = hDestQueue;
|
||||||
queue->wParam32 = wParam;
|
smsg->flags = flags;
|
||||||
queue->lParam = lParam;
|
|
||||||
queue->hPrevSendingTask = destQ->hSendingTask;
|
|
||||||
destQ->hSendingTask = GetFastQueue();
|
|
||||||
|
|
||||||
QUEUE_ClearWakeBit( queue, QS_SMPARAMSFREE );
|
/* add smsg struct in the processing SM list of the source queue */
|
||||||
queue->flags = (queue->flags & ~(QUEUE_SM_WIN32|QUEUE_SM_UNICODE)) | flags;
|
QUEUE_AddSMSG(queue, SM_PROCESSING_LIST, smsg);
|
||||||
|
|
||||||
TRACE(sendmsg,"%*ssm: smResultInit = %08x\n", prevSMRL, "", (unsigned)&qCtrl);
|
/* add smsg struct in the pending list of the destination queue */
|
||||||
|
if (QUEUE_AddSMSG(destQ, SM_PENDING_LIST, smsg) == FALSE)
|
||||||
queue->smResultInit = &qCtrl;
|
return 0;
|
||||||
|
|
||||||
QUEUE_SetWakeBit( destQ, QS_SENDMESSAGE );
|
|
||||||
|
|
||||||
/* perform task switch and wait for the result */
|
/* perform task switch and wait for the result */
|
||||||
|
while( (smsg->flags & SMSG_HAVE_RESULT) == 0 )
|
||||||
while( qCtrl.bPending )
|
|
||||||
{
|
{
|
||||||
if (!(queue->wakeBits & QS_SMRESULT))
|
/* force destination task to run next, if 16 bit threads */
|
||||||
{
|
if (THREAD_IsWin16(THREAD_Current()) && THREAD_IsWin16(destQ->thdb) )
|
||||||
if (THREAD_IsWin16( THREAD_Current() ))
|
|
||||||
DirectedYield( destQ->thdb->teb.htask16 );
|
DirectedYield( destQ->thdb->teb.htask16 );
|
||||||
|
|
||||||
QUEUE_WaitBits( QS_SMRESULT );
|
QUEUE_WaitBits( QS_SMRESULT );
|
||||||
TRACE(sendmsg,"\tsm: have result!\n");
|
|
||||||
}
|
|
||||||
/* got something */
|
|
||||||
|
|
||||||
TRACE(sendmsg,"%*ssm: smResult = %08x\n", prevSMRL, "", (unsigned)queue->smResult );
|
if (! (smsg->flags & SMSG_HAVE_RESULT) )
|
||||||
|
{
|
||||||
if (queue->smResult) { /* FIXME, smResult should always be set */
|
/* not supposed to happen */
|
||||||
queue->smResult->lResult = queue->SendMessageReturn;
|
ERR(sendmsg, "SMSG_HAVE_RESULT not set smsg->flags=%x\n", smsg->flags);
|
||||||
queue->smResult->bPending = FALSE;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lResult = smsg->lResult;
|
||||||
|
TRACE(sendmsg,"smResult = %08x\n", (unsigned)lResult );
|
||||||
|
}
|
||||||
|
|
||||||
QUEUE_ClearWakeBit( queue, QS_SMRESULT );
|
QUEUE_ClearWakeBit( queue, QS_SMRESULT );
|
||||||
|
|
||||||
if( queue->smResult != &qCtrl )
|
|
||||||
ERR(sendmsg, "%*ssm: weird scenes inside the goldmine!\n", prevSMRL, "");
|
|
||||||
}
|
}
|
||||||
queue->smResultInit = NULL;
|
|
||||||
|
|
||||||
TRACE(sendmsg,"%*sSM: [%04x] returning %08lx\n", prevSMRL, "", msg, qCtrl.lResult);
|
/* remove the smsg from the processingg list of the source queue */
|
||||||
debugSMRL-=4;
|
QUEUE_RemoveSMSG( queue, SM_PROCESSING_LIST, smsg );
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
EnterCriticalSection( &queue->cSection );
|
||||||
|
|
||||||
|
if (smsg->flags & SMSG_RECEIVED)
|
||||||
|
HeapFree(SystemHeap, 0, smsg);
|
||||||
|
else
|
||||||
|
smsg->flags |= SMSG_RECEIVER_CLEANS;
|
||||||
|
|
||||||
|
LeaveCriticalSection( &queue->cSection );
|
||||||
|
}
|
||||||
|
|
||||||
QUEUE_Unlock( queue );
|
QUEUE_Unlock( queue );
|
||||||
QUEUE_Unlock( destQ );
|
QUEUE_Unlock( destQ );
|
||||||
|
|
||||||
return qCtrl.lResult;
|
TRACE(sendmsg,"done!\n");
|
||||||
|
return lResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -707,52 +729,81 @@ static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND16 hwnd, UINT16 msg,
|
|||||||
*/
|
*/
|
||||||
void WINAPI ReplyMessage16( LRESULT result )
|
void WINAPI ReplyMessage16( LRESULT result )
|
||||||
{
|
{
|
||||||
MESSAGEQUEUE *senderQ;
|
ReplyMessage32( result );
|
||||||
MESSAGEQUEUE *queue;
|
}
|
||||||
|
|
||||||
if (!(queue = (MESSAGEQUEUE*)QUEUE_Lock( GetFastQueue() ))) return;
|
/***********************************************************************
|
||||||
|
* ReplyMessage (USER.115)
|
||||||
|
*/
|
||||||
|
BOOL32 WINAPI ReplyMessage32( LRESULT result )
|
||||||
|
{
|
||||||
|
MESSAGEQUEUE *senderQ = 0;
|
||||||
|
MESSAGEQUEUE *queue = 0;
|
||||||
|
SMSG *smsg;
|
||||||
|
BOOL32 ret = FALSE;
|
||||||
|
|
||||||
TRACE(msg,"ReplyMessage, queue %04x\n", queue->self);
|
if (!(queue = (MESSAGEQUEUE*)QUEUE_Lock( GetFastQueue() ))) return FALSE;
|
||||||
|
|
||||||
while( (senderQ = (MESSAGEQUEUE*)QUEUE_Lock( queue->InSendMessageHandle)))
|
TRACE(sendmsg,"ReplyMessage, queue %04x\n", queue->self);
|
||||||
|
|
||||||
|
while ((smsg = queue->smWaiting) != 0)
|
||||||
{
|
{
|
||||||
TRACE(msg,"\trpm: replying to %08x (%04x -> %04x)\n",
|
/* if message has already been reply, continue the loop of receving
|
||||||
queue->msg32, queue->self, senderQ->self);
|
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 )
|
if( queue->wakeBits & QS_SENDMESSAGE )
|
||||||
{
|
{
|
||||||
|
/* Note: QUEUE_ReceiveMessage() and ReplyMessage call each other */
|
||||||
QUEUE_ReceiveMessage( queue );
|
QUEUE_ReceiveMessage( queue );
|
||||||
QUEUE_Unlock( senderQ );
|
QUEUE_Unlock( senderQ );
|
||||||
continue; /* ReceiveMessage() already called us */
|
continue; /* ReceiveMessage() already called us */
|
||||||
}
|
}
|
||||||
|
break; /* message to reply is in smsg */
|
||||||
if(!(senderQ->wakeBits & QS_SMRESULT) ) break;
|
|
||||||
if (THREAD_IsWin16(THREAD_Current())) OldYield();
|
|
||||||
|
|
||||||
QUEUE_Unlock( senderQ );
|
|
||||||
}
|
|
||||||
if( !senderQ )
|
|
||||||
{
|
|
||||||
TRACE(msg,"\trpm: done\n");
|
|
||||||
QUEUE_Unlock( queue );
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
senderQ->SendMessageReturn = result;
|
if ( !smsg )
|
||||||
TRACE(msg,"\trpm: smResult = %08x, result = %08lx\n",
|
goto ReplyMessageDone;
|
||||||
(unsigned)queue->smResultCurrent, result );
|
|
||||||
|
|
||||||
senderQ->smResult = queue->smResultCurrent;
|
smsg->lResult = result;
|
||||||
queue->InSendMessageHandle = 0;
|
smsg->flags |= SMSG_ALREADY_REPLIED | SMSG_HAVE_RESULT;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
/* tell the sending task that its reply is ready */
|
||||||
QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
|
QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
|
||||||
|
|
||||||
|
/* switch directly to sending task (16 bit thread only) */
|
||||||
if (THREAD_IsWin16( THREAD_Current() ))
|
if (THREAD_IsWin16( THREAD_Current() ))
|
||||||
DirectedYield( senderQ->thdb->teb.htask16 );
|
DirectedYield( senderQ->thdb->teb.htask16 );
|
||||||
|
|
||||||
QUEUE_Unlock( senderQ );
|
ret = TRUE;
|
||||||
QUEUE_Unlock( queue );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ReplyMessageDone:
|
||||||
|
if ( senderQ )
|
||||||
|
QUEUE_Unlock( senderQ );
|
||||||
|
if ( queue )
|
||||||
|
QUEUE_Unlock( queue );
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* MSG_PeekMessage
|
* MSG_PeekMessage
|
||||||
@ -1454,7 +1505,7 @@ LRESULT WINAPI SendMessage32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
|
|||||||
|
|
||||||
if (wndPtr->hmemTaskQ != GetFastQueue())
|
if (wndPtr->hmemTaskQ != GetFastQueue())
|
||||||
ret = MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam,
|
ret = MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam,
|
||||||
QUEUE_SM_WIN32 );
|
SMSG_WIN32 );
|
||||||
else
|
else
|
||||||
ret = CallWindowProc32A( (WNDPROC32)wndPtr->winproc,
|
ret = CallWindowProc32A( (WNDPROC32)wndPtr->winproc,
|
||||||
hwnd, msg, wParam, lParam );
|
hwnd, msg, wParam, lParam );
|
||||||
@ -1525,7 +1576,7 @@ LRESULT WINAPI SendMessage32W(
|
|||||||
|
|
||||||
if (wndPtr->hmemTaskQ != GetFastQueue())
|
if (wndPtr->hmemTaskQ != GetFastQueue())
|
||||||
ret = MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam,
|
ret = MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam,
|
||||||
QUEUE_SM_WIN32 | QUEUE_SM_UNICODE );
|
SMSG_WIN32 | SMSG_UNICODE );
|
||||||
else
|
else
|
||||||
ret = CallWindowProc32W( (WNDPROC32)wndPtr->winproc,
|
ret = CallWindowProc32W( (WNDPROC32)wndPtr->winproc,
|
||||||
hwnd, msg, wParam, lParam );
|
hwnd, msg, wParam, lParam );
|
||||||
@ -2115,7 +2166,7 @@ BOOL32 WINAPI InSendMessage32(void)
|
|||||||
|
|
||||||
if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue() )))
|
if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue() )))
|
||||||
return 0;
|
return 0;
|
||||||
ret = (BOOL32)queue->InSendMessageHandle;
|
ret = (BOOL32)queue->smProcessing;
|
||||||
|
|
||||||
QUEUE_Unlock( queue );
|
QUEUE_Unlock( queue );
|
||||||
return ret;
|
return ret;
|
||||||
|
402
windows/queue.c
402
windows/queue.c
@ -19,6 +19,7 @@
|
|||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "spy.h"
|
||||||
|
|
||||||
#define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
|
#define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
|
||||||
|
|
||||||
@ -359,23 +360,21 @@ void QUEUE_DumpQueue( HQUEUE16 hQueue )
|
|||||||
|
|
||||||
DUMP( "next: %12.4x Intertask SendMessage:\n"
|
DUMP( "next: %12.4x Intertask SendMessage:\n"
|
||||||
"thread: %10p ----------------------\n"
|
"thread: %10p ----------------------\n"
|
||||||
"hWnd: %12.8x\n"
|
"firstMsg: %8p smWaiting: %10p\n"
|
||||||
"firstMsg: %8p msg: %11.8x\n"
|
"lastMsg: %8p smPending: %10p\n"
|
||||||
"lastMsg: %8p wParam: %10.8x\n"
|
"msgCount: %8.4x smProcessing: %10p\n"
|
||||||
"msgCount: %8.4x lParam: %10.8x\n"
|
"lockCount: %7.4x\n"
|
||||||
"lockCount: %7.4x lRet: %12.8x\n"
|
"wWinVer: %9.4x\n"
|
||||||
"wWinVer: %9.4x ISMH: %10.4x\n"
|
"paints: %10.4x\n"
|
||||||
"paints: %10.4x hSendTask: %5.4x\n"
|
"timers: %10.4x\n"
|
||||||
"timers: %10.4x hPrevSend: %5.4x\n"
|
|
||||||
"wakeBits: %8.4x\n"
|
"wakeBits: %8.4x\n"
|
||||||
"wakeMask: %8.4x\n"
|
"wakeMask: %8.4x\n"
|
||||||
"hCurHook: %8.4x\n",
|
"hCurHook: %8.4x\n",
|
||||||
pq->next, pq->thdb, pq->hWnd32, pq->firstMsg, pq->msg32,
|
pq->next, pq->thdb, pq->firstMsg, pq->smWaiting, pq->lastMsg,
|
||||||
pq->lastMsg, pq->wParam32, pq->msgCount, (unsigned)pq->lParam,
|
pq->smPending, pq->msgCount, pq->smProcessing,
|
||||||
(unsigned)pq->lockCount, (unsigned)pq->SendMessageReturn,
|
(unsigned)pq->lockCount, pq->wWinVersion,
|
||||||
pq->wWinVersion, pq->InSendMessageHandle,
|
pq->wPaintCount, pq->wTimerCount,
|
||||||
pq->wPaintCount, pq->hSendingTask, pq->wTimerCount,
|
pq->wakeBits, pq->wakeMask, pq->hCurHook);
|
||||||
pq->hPrevSendingTask, pq->wakeBits, pq->wakeMask, pq->hCurHook);
|
|
||||||
|
|
||||||
QUEUE_Unlock( pq );
|
QUEUE_Unlock( pq );
|
||||||
}
|
}
|
||||||
@ -449,7 +448,7 @@ static HQUEUE16 QUEUE_CreateMsgQueue( BOOL16 bCreatePerQData )
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
msgQueue->self = hQueue;
|
msgQueue->self = hQueue;
|
||||||
msgQueue->wakeBits = msgQueue->changeBits = QS_SMPARAMSFREE;
|
msgQueue->wakeBits = msgQueue->changeBits = 0;
|
||||||
msgQueue->wWinVersion = pTask ? pTask->version : 0;
|
msgQueue->wWinVersion = pTask ? pTask->version : 0;
|
||||||
|
|
||||||
InitializeCriticalSection( &msgQueue->cSection );
|
InitializeCriticalSection( &msgQueue->cSection );
|
||||||
@ -481,6 +480,44 @@ static HQUEUE16 QUEUE_CreateMsgQueue( BOOL16 bCreatePerQData )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* QUEUE_FlushMessage
|
||||||
|
*
|
||||||
|
* Try to reply to all pending sent messages on exit.
|
||||||
|
*/
|
||||||
|
void QUEUE_FlushMessages( MESSAGEQUEUE *queue )
|
||||||
|
{
|
||||||
|
SMSG *smsg;
|
||||||
|
MESSAGEQUEUE *senderQ = 0;
|
||||||
|
|
||||||
|
if( queue )
|
||||||
|
{
|
||||||
|
EnterCriticalSection( &queue->cSection );
|
||||||
|
|
||||||
|
/* empty the list of pending SendMessage waiting to be received */
|
||||||
|
while (queue->smPending)
|
||||||
|
{
|
||||||
|
smsg = QUEUE_RemoveSMSG( queue, SM_PENDING_LIST, 0);
|
||||||
|
|
||||||
|
senderQ = (MESSAGEQUEUE*)QUEUE_Lock( smsg->hSrcQueue );
|
||||||
|
if ( !senderQ )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* return 0, to unblock other thread */
|
||||||
|
smsg->lResult = 0;
|
||||||
|
smsg->flags |= SMSG_HAVE_RESULT;
|
||||||
|
QUEUE_SetWakeBit( senderQ, QS_SMRESULT);
|
||||||
|
|
||||||
|
QUEUE_Unlock( senderQ );
|
||||||
|
}
|
||||||
|
|
||||||
|
QUEUE_ClearWakeBit( queue, QS_SENDMESSAGE );
|
||||||
|
|
||||||
|
LeaveCriticalSection( &queue->cSection );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* QUEUE_DeleteMsgQueue
|
* QUEUE_DeleteMsgQueue
|
||||||
*
|
*
|
||||||
@ -492,7 +529,6 @@ static HQUEUE16 QUEUE_CreateMsgQueue( BOOL16 bCreatePerQData )
|
|||||||
BOOL32 QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
|
BOOL32 QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
|
||||||
{
|
{
|
||||||
MESSAGEQUEUE * msgQueue = (MESSAGEQUEUE*)QUEUE_Lock(hQueue);
|
MESSAGEQUEUE * msgQueue = (MESSAGEQUEUE*)QUEUE_Lock(hQueue);
|
||||||
HQUEUE16 senderQ;
|
|
||||||
HQUEUE16 *pPrev;
|
HQUEUE16 *pPrev;
|
||||||
|
|
||||||
TRACE(msg,"(): Deleting message queue %04x\n", hQueue);
|
TRACE(msg,"(): Deleting message queue %04x\n", hQueue);
|
||||||
@ -509,16 +545,7 @@ BOOL32 QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
|
|||||||
if( hActiveQueue == hQueue ) hActiveQueue = 0;
|
if( hActiveQueue == hQueue ) hActiveQueue = 0;
|
||||||
|
|
||||||
/* flush sent messages */
|
/* flush sent messages */
|
||||||
senderQ = msgQueue->hSendingTask;
|
QUEUE_FlushMessages( msgQueue );
|
||||||
while( senderQ )
|
|
||||||
{
|
|
||||||
MESSAGEQUEUE* sq = (MESSAGEQUEUE*)QUEUE_Lock(senderQ);
|
|
||||||
if( !sq ) break;
|
|
||||||
sq->SendMessageReturn = 0L;
|
|
||||||
QUEUE_SetWakeBit( sq, QS_SMRESULT );
|
|
||||||
senderQ = sq->hPrevSendingTask;
|
|
||||||
QUEUE_Unlock(sq);
|
|
||||||
}
|
|
||||||
|
|
||||||
SYSTEM_LOCK();
|
SYSTEM_LOCK();
|
||||||
|
|
||||||
@ -686,6 +713,148 @@ void QUEUE_WaitBits( WORD bits )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* QUEUE_AddSMSG
|
||||||
|
*
|
||||||
|
* This routine is called when a SMSG need to be added to one of the three
|
||||||
|
* SM list. (SM_PROCESSING_LIST, SM_PENDING_LIST, SM_WAITING_LIST)
|
||||||
|
*/
|
||||||
|
BOOL32 QUEUE_AddSMSG( MESSAGEQUEUE *queue, int list, SMSG *smsg )
|
||||||
|
{
|
||||||
|
TRACE(sendmsg,"queue=%x, list=%d, smsg=%p msg=%s\n", queue->self, list,
|
||||||
|
smsg, SPY_GetMsgName(smsg->msg));
|
||||||
|
|
||||||
|
switch (list)
|
||||||
|
{
|
||||||
|
case SM_PROCESSING_LIST:
|
||||||
|
/* don't need to be thread safe, only accessed by the
|
||||||
|
thread associated with the sender queue */
|
||||||
|
smsg->nextProcessing = queue->smProcessing;
|
||||||
|
queue->smProcessing = smsg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SM_WAITING_LIST:
|
||||||
|
/* don't need to be thread safe, only accessed by the
|
||||||
|
thread associated with the receiver queue */
|
||||||
|
smsg->nextWaiting = queue->smWaiting;
|
||||||
|
queue->smWaiting = smsg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SM_PENDING_LIST:
|
||||||
|
/* make it thread safe, could be accessed by the sender and
|
||||||
|
receiver thread */
|
||||||
|
|
||||||
|
EnterCriticalSection( &queue->cSection );
|
||||||
|
smsg->nextPending = queue->smPending;
|
||||||
|
queue->smPending = smsg;
|
||||||
|
QUEUE_SetWakeBit( queue, QS_SENDMESSAGE );
|
||||||
|
LeaveCriticalSection( &queue->cSection );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
WARN(sendmsg, "Invalid list: %d", list);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* QUEUE_RemoveSMSG
|
||||||
|
*
|
||||||
|
* This routine is called when a SMSG need to be remove from one of the three
|
||||||
|
* SM list. (SM_PROCESSING_LIST, SM_PENDING_LIST, SM_WAITING_LIST)
|
||||||
|
* If smsg == 0, remove the first smsg from the specified list
|
||||||
|
*/
|
||||||
|
SMSG *QUEUE_RemoveSMSG( MESSAGEQUEUE *queue, int list, SMSG *smsg )
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (list)
|
||||||
|
{
|
||||||
|
case SM_PROCESSING_LIST:
|
||||||
|
/* don't need to be thread safe, only accessed by the
|
||||||
|
thread associated with the sender queue */
|
||||||
|
|
||||||
|
/* if smsg is equal to null, it means the first in the list */
|
||||||
|
if (!smsg)
|
||||||
|
smsg = queue->smProcessing;
|
||||||
|
|
||||||
|
TRACE(sendmsg,"queue=%x, list=%d, smsg=%p msg=%s\n", queue->self, list,
|
||||||
|
smsg, SPY_GetMsgName(smsg->msg));
|
||||||
|
/* In fact SM_PROCESSING_LIST is a stack, and smsg
|
||||||
|
should be always at the top of the list */
|
||||||
|
if ( (smsg != queue->smProcessing) || !queue->smProcessing )
|
||||||
|
{
|
||||||
|
ERR( sendmsg, "smsg not at the top of Processing list, smsg=0x%p queue=0x%p", smsg, queue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
queue->smProcessing = smsg->nextProcessing;
|
||||||
|
smsg->nextProcessing = 0;
|
||||||
|
}
|
||||||
|
return smsg;
|
||||||
|
|
||||||
|
case SM_WAITING_LIST:
|
||||||
|
/* don't need to be thread safe, only accessed by the
|
||||||
|
thread associated with the receiver queue */
|
||||||
|
|
||||||
|
/* if smsg is equal to null, it means the first in the list */
|
||||||
|
if (!smsg)
|
||||||
|
smsg = queue->smWaiting;
|
||||||
|
|
||||||
|
TRACE(sendmsg,"queue=%x, list=%d, smsg=%p msg=%s\n", queue->self, list,
|
||||||
|
smsg, SPY_GetMsgName(smsg->msg));
|
||||||
|
/* In fact SM_WAITING_LIST is a stack, and smsg
|
||||||
|
should be always at the top of the list */
|
||||||
|
if ( (smsg != queue->smWaiting) || !queue->smWaiting )
|
||||||
|
{
|
||||||
|
ERR( sendmsg, "smsg not at the top of Waiting list, smsg=0x%p queue=0x%p", smsg, queue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
queue->smWaiting = smsg->nextWaiting;
|
||||||
|
smsg->nextWaiting = 0;
|
||||||
|
}
|
||||||
|
return smsg;
|
||||||
|
|
||||||
|
case SM_PENDING_LIST:
|
||||||
|
/* make it thread safe, could be accessed by the sender and
|
||||||
|
receiver thread */
|
||||||
|
EnterCriticalSection( &queue->cSection );
|
||||||
|
|
||||||
|
if (!smsg || !queue->smPending)
|
||||||
|
smsg = queue->smPending;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR( sendmsg, "should always remove the top one in Pending list, smsg=0x%p queue=0x%p", smsg, queue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE(sendmsg,"queue=%x, list=%d, smsg=%p msg=%s\n", queue->self, list,
|
||||||
|
smsg, SPY_GetMsgName(smsg->msg));
|
||||||
|
|
||||||
|
queue->smPending = smsg->nextPending;
|
||||||
|
smsg->nextPending = 0;
|
||||||
|
|
||||||
|
/* if no more SMSG in Pending list, clear QS_SENDMESSAGE flag */
|
||||||
|
if (!queue->smPending)
|
||||||
|
QUEUE_ClearWakeBit( queue, QS_SENDMESSAGE );
|
||||||
|
|
||||||
|
LeaveCriticalSection( &queue->cSection );
|
||||||
|
return smsg;
|
||||||
|
|
||||||
|
default:
|
||||||
|
WARN(sendmsg, "Invalid list: %d", list);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* QUEUE_ReceiveMessage
|
* QUEUE_ReceiveMessage
|
||||||
*
|
*
|
||||||
@ -693,123 +862,116 @@ void QUEUE_WaitBits( WORD bits )
|
|||||||
*/
|
*/
|
||||||
void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue )
|
void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue )
|
||||||
{
|
{
|
||||||
MESSAGEQUEUE *senderQ = NULL;
|
|
||||||
HQUEUE16 prevSender = 0;
|
|
||||||
QSMCTRL* prevCtrlPtr = NULL;
|
|
||||||
LRESULT result = 0;
|
LRESULT result = 0;
|
||||||
|
SMSG *smsg;
|
||||||
|
MESSAGEQUEUE *senderQ;
|
||||||
|
|
||||||
TRACE(msg, "ReceiveMessage, queue %04x\n", queue->self );
|
TRACE(sendmsg, "queue %04x\n", queue->self );
|
||||||
if (!(queue->wakeBits & QS_SENDMESSAGE) ||
|
|
||||||
!(senderQ = (MESSAGEQUEUE*)QUEUE_Lock( queue->hSendingTask)))
|
|
||||||
{ TRACE(msg,"\trcm: nothing to do\n"); return; }
|
|
||||||
|
|
||||||
if( !senderQ->hPrevSendingTask )
|
if ( !(queue->wakeBits & QS_SENDMESSAGE) && queue->smPending )
|
||||||
QUEUE_ClearWakeBit( queue, QS_SENDMESSAGE ); /* no more sent messages */
|
{
|
||||||
|
TRACE(sendmsg,"\trcm: nothing to do\n");
|
||||||
/* Save current state on stack */
|
return;
|
||||||
prevSender = queue->InSendMessageHandle;
|
}
|
||||||
prevCtrlPtr = queue->smResultCurrent;
|
|
||||||
|
/* remove smsg on the top of the pending list and put it in the processing list */
|
||||||
/* Remove sending queue from the list */
|
smsg = QUEUE_RemoveSMSG(queue, SM_PENDING_LIST, 0);
|
||||||
queue->InSendMessageHandle = queue->hSendingTask;
|
QUEUE_AddSMSG(queue, SM_WAITING_LIST, smsg);
|
||||||
queue->smResultCurrent = senderQ->smResultInit;
|
|
||||||
queue->hSendingTask = senderQ->hPrevSendingTask;
|
TRACE(sendmsg,"RM: %s [%04x] (%04x -> %04x)\n",
|
||||||
|
SPY_GetMsgName(smsg->msg), smsg->msg, smsg->hSrcQueue, smsg->hDstQueue );
|
||||||
TRACE(msg, "\trcm: smResultCurrent = %08x, prevCtrl = %08x\n",
|
|
||||||
(unsigned)queue->smResultCurrent, (unsigned)prevCtrlPtr );
|
if (IsWindow32( smsg->hWnd ))
|
||||||
QUEUE_SetWakeBit( senderQ, QS_SMPARAMSFREE );
|
{
|
||||||
|
WND *wndPtr = WIN_FindWndPtr( smsg->hWnd );
|
||||||
TRACE(msg, "\trcm: calling wndproc - %08x %08x %08x %08x\n",
|
DWORD extraInfo = queue->GetMessageExtraInfoVal; /* save ExtraInfo */
|
||||||
senderQ->hWnd32, senderQ->msg32,
|
|
||||||
senderQ->wParam32, (unsigned)senderQ->lParam );
|
/* use sender queue extra info value while calling the window proc */
|
||||||
|
senderQ = (MESSAGEQUEUE*)QUEUE_Lock( smsg->hSrcQueue );
|
||||||
if (IsWindow32( senderQ->hWnd32 ))
|
if (senderQ)
|
||||||
{
|
{
|
||||||
WND *wndPtr = WIN_FindWndPtr( senderQ->hWnd32 );
|
|
||||||
DWORD extraInfo = queue->GetMessageExtraInfoVal;
|
|
||||||
queue->GetMessageExtraInfoVal = senderQ->GetMessageExtraInfoVal;
|
queue->GetMessageExtraInfoVal = senderQ->GetMessageExtraInfoVal;
|
||||||
|
QUEUE_Unlock( senderQ );
|
||||||
|
}
|
||||||
|
|
||||||
if (senderQ->flags & QUEUE_SM_WIN32)
|
/* call the right version of CallWindowProcXX */
|
||||||
|
if (smsg->flags & SMSG_WIN32)
|
||||||
{
|
{
|
||||||
TRACE(msg, "\trcm: msg is Win32\n" );
|
TRACE(sendmsg, "\trcm: msg is Win32\n" );
|
||||||
if (senderQ->flags & QUEUE_SM_UNICODE)
|
if (smsg->flags & SMSG_UNICODE)
|
||||||
result = CallWindowProc32W( wndPtr->winproc,
|
result = CallWindowProc32W( wndPtr->winproc,
|
||||||
senderQ->hWnd32, senderQ->msg32,
|
smsg->hWnd, smsg->msg,
|
||||||
senderQ->wParam32, senderQ->lParam );
|
smsg->wParam, smsg->lParam );
|
||||||
else
|
else
|
||||||
result = CallWindowProc32A( wndPtr->winproc,
|
result = CallWindowProc32A( wndPtr->winproc,
|
||||||
senderQ->hWnd32, senderQ->msg32,
|
smsg->hWnd, smsg->msg,
|
||||||
senderQ->wParam32, senderQ->lParam );
|
smsg->wParam, smsg->lParam );
|
||||||
}
|
}
|
||||||
else /* Win16 message */
|
else /* Win16 message */
|
||||||
result = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
|
result = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
|
||||||
(HWND16) senderQ->hWnd32,
|
(HWND16) smsg->hWnd,
|
||||||
(UINT16) senderQ->msg32,
|
(UINT16) smsg->msg,
|
||||||
LOWORD (senderQ->wParam32),
|
LOWORD (smsg->wParam),
|
||||||
senderQ->lParam );
|
smsg->lParam );
|
||||||
|
|
||||||
queue->GetMessageExtraInfoVal = extraInfo; /* Restore extra info */
|
queue->GetMessageExtraInfoVal = extraInfo; /* Restore extra info */
|
||||||
TRACE(msg,"\trcm: result = %08x\n", (unsigned)result );
|
TRACE(sendmsg,"result = %08x\n", (unsigned)result );
|
||||||
}
|
}
|
||||||
else WARN(msg, "\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 );
|
QUEUE_Unlock( senderQ );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* no early reply, so do it now */
|
||||||
|
|
||||||
/* Return the result to the sender task */
|
/* set SMSG_SENDING_REPLY flag to tell ReplyMessage16, it's not
|
||||||
ReplyMessage16( result );
|
an early reply */
|
||||||
|
smsg->flags |= SMSG_SENDING_REPLY;
|
||||||
|
ReplyMessage32( result );
|
||||||
|
}
|
||||||
|
|
||||||
queue->InSendMessageHandle = prevSender;
|
TRACE( sendmsg,"done! \n" );
|
||||||
queue->smResultCurrent = prevCtrlPtr;
|
|
||||||
|
|
||||||
TRACE(msg,"done!\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* QUEUE_FlushMessage
|
|
||||||
*
|
|
||||||
* Try to reply to all pending sent messages on exit.
|
|
||||||
*/
|
|
||||||
void QUEUE_FlushMessages( HQUEUE16 hQueue )
|
|
||||||
{
|
|
||||||
MESSAGEQUEUE *queue = (MESSAGEQUEUE*)QUEUE_Lock( hQueue );
|
|
||||||
|
|
||||||
if( queue )
|
|
||||||
{
|
|
||||||
MESSAGEQUEUE *senderQ = (MESSAGEQUEUE*)QUEUE_Lock( queue->hSendingTask );
|
|
||||||
QSMCTRL* CtrlPtr = queue->smResultCurrent;
|
|
||||||
|
|
||||||
TRACE(msg,"Flushing queue %04x:\n", hQueue );
|
|
||||||
|
|
||||||
while( senderQ )
|
|
||||||
{
|
|
||||||
if( !CtrlPtr )
|
|
||||||
CtrlPtr = senderQ->smResultInit;
|
|
||||||
|
|
||||||
TRACE(msg,"\tfrom queue %04x, smResult %08x\n", queue->hSendingTask, (unsigned)CtrlPtr );
|
|
||||||
|
|
||||||
if( !(queue->hSendingTask = senderQ->hPrevSendingTask) )
|
|
||||||
QUEUE_ClearWakeBit( queue, QS_SENDMESSAGE );
|
|
||||||
|
|
||||||
QUEUE_SetWakeBit( senderQ, QS_SMPARAMSFREE );
|
|
||||||
|
|
||||||
queue->smResultCurrent = CtrlPtr;
|
|
||||||
while( senderQ->wakeBits & QS_SMRESULT ) OldYield();
|
|
||||||
|
|
||||||
senderQ->SendMessageReturn = 0;
|
|
||||||
senderQ->smResult = queue->smResultCurrent;
|
|
||||||
QUEUE_SetWakeBit( senderQ, QS_SMRESULT);
|
|
||||||
|
|
||||||
QUEUE_Unlock( senderQ );
|
|
||||||
|
|
||||||
senderQ = (MESSAGEQUEUE*)QUEUE_Lock( queue->hSendingTask );
|
|
||||||
CtrlPtr = NULL;
|
|
||||||
}
|
|
||||||
queue->InSendMessageHandle = 0;
|
|
||||||
|
|
||||||
QUEUE_Unlock( queue );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* QUEUE_AddMsg
|
* QUEUE_AddMsg
|
||||||
|
@ -173,7 +173,6 @@ void USER_QueueCleanup( HQUEUE16 hQueue )
|
|||||||
|
|
||||||
TIMER_RemoveQueueTimers( hQueue );
|
TIMER_RemoveQueueTimers( hQueue );
|
||||||
|
|
||||||
QUEUE_FlushMessages( hQueue );
|
|
||||||
HOOK_FreeQueueHooks( hQueue );
|
HOOK_FreeQueueHooks( hQueue );
|
||||||
|
|
||||||
QUEUE_SetExitingQueue( hQueue );
|
QUEUE_SetExitingQueue( hQueue );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user