Commit 1c4786fe authored by Stephane Lussier's avatar Stephane Lussier Committed by Alexandre Julliard

- Made the message queue access to be thread safe. (Using two new

functions to access the message queue, QUEUE_Lock(), QUEUE_Unlock() instead of GlobalLock16()). - Fixed QUEUE_DumpQueue (used by "info queue <handle>" with the wine-debugger).
parent 03479f8a
......@@ -44,6 +44,9 @@ typedef struct tagMESSAGEQUEUE
HANDLE32 hEvent; /* Event handle */
CRITICAL_SECTION cSection; /* Queue access critical section */
DWORD magic; /* magic number should be QUEUE_MAGIC */
DWORD lockCount; /* reference counter */
WORD flags; /* Queue flags */
WORD wWinVersion; /* Expected Windows version */
......@@ -94,6 +97,10 @@ typedef struct tagMESSAGEQUEUE
#define QUEUE_SM_WIN32 0x0002 /* Currently sent message is Win32 */
#define QUEUE_SM_UNICODE 0x0004 /* Currently sent message is Unicode */
#define QUEUE_MAGIC 0xD46E80AF
extern MESSAGEQUEUE *QUEUE_Lock( HQUEUE16 hQueue );
extern void QUEUE_Unlock( MESSAGEQUEUE *queue );
extern void QUEUE_DumpQueue( HQUEUE16 hQueue );
extern void QUEUE_WalkQueues(void);
extern BOOL32 QUEUE_IsExitingQueue( HQUEUE16 hQueue );
......
......@@ -827,9 +827,11 @@ static HANDLE16 HOOK_GetHook( INT16 id, HQUEUE16 hQueue )
MESSAGEQUEUE *queue;
HANDLE16 hook = 0;
if ((queue = (MESSAGEQUEUE *)GlobalLock16( hQueue )) != NULL)
if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
hook = queue->hooks[id - WH_MINHOOK];
if (!hook) hook = HOOK_systemHooks[id - WH_MINHOOK];
QUEUE_Unlock( queue );
return hook;
}
......@@ -878,9 +880,10 @@ static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT32 type,
if (hQueue)
{
MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
data->next = queue->hooks[id - WH_MINHOOK];
queue->hooks[id - WH_MINHOOK] = handle;
QUEUE_Unlock( queue );
}
else
{
......@@ -921,9 +924,10 @@ static BOOL32 HOOK_RemoveHook( HANDLE16 hook )
if (data->ownerQueue)
{
MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( data->ownerQueue );
MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( data->ownerQueue );
if (!queue) return FALSE;
prevHook = &queue->hooks[data->id - WH_MINHOOK];
QUEUE_Unlock( queue );
}
else prevHook = &HOOK_systemHooks[data->id - WH_MINHOOK];
......@@ -979,7 +983,7 @@ static LRESULT HOOK_CallHook( HANDLE16 hook, INT32 fromtype, INT32 code,
/* Now call it */
if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetFastQueue() ))) return 0;
if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue() ))) return 0;
prevHook = queue->hCurHook;
queue->hCurHook = hook;
data->flags |= HOOK_INUSE;
......@@ -994,6 +998,8 @@ static LRESULT HOOK_CallHook( HANDLE16 hook, INT32 fromtype, INT32 code,
data->flags &= ~HOOK_INUSE;
queue->hCurHook = prevHook;
QUEUE_Unlock( queue );
if (UnMapFunc)
UnMapFunc( data->id, code, wParamOrig, lParamOrig, wParam, lParam );
......@@ -1089,7 +1095,7 @@ void HOOK_ResetQueueHooks( HQUEUE16 hQueue )
{
MESSAGEQUEUE *queue;
if ((queue = (MESSAGEQUEUE *)GlobalLock16( hQueue )) != NULL)
if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
{
HOOKDATA* data;
HHOOK hook;
......@@ -1106,6 +1112,8 @@ void HOOK_ResetQueueHooks( HQUEUE16 hQueue )
} else break;
}
}
QUEUE_Unlock( queue );
}
}
......@@ -1329,9 +1337,12 @@ LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wParam, LPARAM lParam,
/* Note: the *hhook parameter is never used, since we rely on the
* current hook value from the task queue to find the next hook. */
MESSAGEQUEUE *queue;
LRESULT ret;
if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetFastQueue() ))) return 0;
return CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue() ))) return 0;
ret = CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
QUEUE_Unlock( queue );
return ret;
}
......
......@@ -36,8 +36,7 @@
typedef enum { SYSQ_MSG_ABANDON, SYSQ_MSG_SKIP,
SYSQ_MSG_ACCEPT, SYSQ_MSG_CONTINUE } SYSQ_STATUS;
extern MESSAGEQUEUE *pCursorQueue; /* queue.c */
extern MESSAGEQUEUE *pActiveQueue;
extern HQUEUE16 hCursorQueue; /* queue.c */
DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
......@@ -102,7 +101,7 @@ static DWORD MSG_TranslateMouseMsg( HWND16 hTopWnd, DWORD filter,
UINT16 message = msg->message;
POINT16 screen_pt, pt;
HANDLE16 hQ = GetFastQueue();
MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16(hQ);
MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock(hQ);
BOOL32 eatMsg = FALSE;
BOOL32 mouseClick = ((message == WM_LBUTTONDOWN) ||
(message == WM_RBUTTONDOWN) ||
......@@ -133,15 +132,22 @@ static DWORD MSG_TranslateMouseMsg( HWND16 hTopWnd, DWORD filter,
/* Not for the current task */
if (queue) QUEUE_ClearWakeBit( queue, QS_MOUSE );
/* Wake up the other task */
queue = (MESSAGEQUEUE *)GlobalLock16( pWnd->hmemTaskQ );
QUEUE_Unlock( queue );
queue = (MESSAGEQUEUE *)QUEUE_Lock( pWnd->hmemTaskQ );
if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE );
QUEUE_Unlock( queue );
return SYSQ_MSG_ABANDON;
}
/* check if hWnd is within hWndScope */
if( hTopWnd && hWnd != hTopWnd )
if( !IsChild16(hTopWnd, hWnd) ) return SYSQ_MSG_CONTINUE;
if( !IsChild16(hTopWnd, hWnd) )
{
QUEUE_Unlock( queue );
return SYSQ_MSG_CONTINUE;
}
if( mouseClick )
{
......@@ -172,9 +178,14 @@ static DWORD MSG_TranslateMouseMsg( HWND16 hTopWnd, DWORD filter,
/* check message filter */
if (!MSG_CheckFilter(message, filter)) return SYSQ_MSG_CONTINUE;
if (!MSG_CheckFilter(message, filter))
{
QUEUE_Unlock(queue);
return SYSQ_MSG_CONTINUE;
}
pCursorQueue = queue;
hCursorQueue = queue->self;
QUEUE_Unlock(queue);
/* call WH_MOUSE */
......@@ -280,11 +291,14 @@ static DWORD MSG_TranslateKbdMsg( HWND16 hTopWnd, DWORD filter,
if (pWnd && (pWnd->hmemTaskQ != GetFastQueue()))
{
/* Not for the current task */
MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( GetFastQueue() );
MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue() );
if (queue) QUEUE_ClearWakeBit( queue, QS_KEY );
QUEUE_Unlock( queue );
/* Wake up the other task */
queue = (MESSAGEQUEUE *)GlobalLock16( pWnd->hmemTaskQ );
queue = (MESSAGEQUEUE *)QUEUE_Lock( pWnd->hmemTaskQ );
if (queue) QUEUE_SetWakeBit( queue, QS_KEY );
QUEUE_Unlock( queue );
return SYSQ_MSG_ABANDON;
}
......@@ -603,10 +617,16 @@ static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND16 hwnd, UINT16 msg,
QSMCTRL qCtrl = { 0, 1};
MESSAGEQUEUE *queue, *destQ;
if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetFastQueue() ))) return 0;
if (!(destQ = (MESSAGEQUEUE*)GlobalLock16( hDestQueue ))) return 0;
if (IsTaskLocked() || !IsWindow32(hwnd))
return 0;
if (!(queue = (MESSAGEQUEUE*)QUEUE_Lock( GetFastQueue() ))) return 0;
if (IsTaskLocked() || !IsWindow32(hwnd)) return 0;
if (!(destQ = (MESSAGEQUEUE*)QUEUE_Lock( hDestQueue )))
{
QUEUE_Unlock( queue );
return 0;
}
debugSMRL+=4;
TRACE(sendmsg,"%*sSM: %s [%04x] (%04x -> %04x)\n",
......@@ -664,6 +684,9 @@ static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND16 hwnd, UINT16 msg,
TRACE(sendmsg,"%*sSM: [%04x] returning %08lx\n", prevSMRL, "", msg, qCtrl.lResult);
debugSMRL-=4;
QUEUE_Unlock( queue );
QUEUE_Unlock( destQ );
return qCtrl.lResult;
}
......@@ -676,11 +699,11 @@ void WINAPI ReplyMessage16( LRESULT result )
MESSAGEQUEUE *senderQ;
MESSAGEQUEUE *queue;
if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetFastQueue() ))) return;
if (!(queue = (MESSAGEQUEUE*)QUEUE_Lock( GetFastQueue() ))) return;
TRACE(msg,"ReplyMessage, queue %04x\n", queue->self);
while( (senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->InSendMessageHandle)))
while( (senderQ = (MESSAGEQUEUE*)QUEUE_Lock( queue->InSendMessageHandle)))
{
TRACE(msg,"\trpm: replying to %08x (%04x -> %04x)\n",
queue->msg32, queue->self, senderQ->self);
......@@ -688,13 +711,21 @@ void WINAPI ReplyMessage16( LRESULT result )
if( queue->wakeBits & QS_SENDMESSAGE )
{
QUEUE_ReceiveMessage( queue );
QUEUE_Unlock( senderQ );
continue; /* ReceiveMessage() already called us */
}
if(!(senderQ->wakeBits & QS_SMRESULT) ) break;
if (THREAD_IsWin16(THREAD_Current())) OldYield();
QUEUE_Unlock( senderQ );
}
if( !senderQ ) { TRACE(msg,"\trpm: done\n"); return; }
if( !senderQ )
{
TRACE(msg,"\trpm: done\n");
QUEUE_Unlock( queue );
return;
}
senderQ->SendMessageReturn = result;
TRACE(msg,"\trpm: smResult = %08x, result = %08lx\n",
......@@ -706,6 +737,9 @@ void WINAPI ReplyMessage16( LRESULT result )
QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
if (THREAD_IsWin16( THREAD_Current() ))
DirectedYield( senderQ->thdb->teb.htask16 );
QUEUE_Unlock( senderQ );
QUEUE_Unlock( queue );
}
......@@ -746,7 +780,7 @@ static BOOL32 MSG_PeekMessage( LPMSG16 msg, HWND16 hwnd, WORD first, WORD last,
QMSG *qmsg;
hQueue = GetFastQueue();
msgQueue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
msgQueue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
if (!msgQueue) return FALSE;
msgQueue->changeBits = 0;
......@@ -852,12 +886,19 @@ static BOOL32 MSG_PeekMessage( LPMSG16 msg, HWND16 hwnd, WORD first, WORD last,
if (peek)
{
if (!(flags & PM_NOYIELD)) UserYield();
QUEUE_Unlock( msgQueue );
return FALSE;
}
msgQueue->wakeMask = mask;
QUEUE_WaitBits( mask );
QUEUE_Unlock( msgQueue );
}
/* instead of unlocking queue for every break condition, all break
condition will fall here */
QUEUE_Unlock( msgQueue );
/* We got a message */
if (flags & PM_REMOVE)
{
......@@ -1557,18 +1598,21 @@ DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, HANDLE32 *pHandles,
TDB *currTask = (TDB *)GlobalLock16( GetCurrentTask() );
HQUEUE16 hQueue = currTask? currTask->hQueue : 0;
MESSAGEQUEUE *msgQueue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
MESSAGEQUEUE *msgQueue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
if (!msgQueue) return WAIT_FAILED;
if (nCount > MAXIMUM_WAIT_OBJECTS-1)
{
SetLastError( ERROR_INVALID_PARAMETER );
QUEUE_Unlock( msgQueue );
return WAIT_FAILED;
}
msgQueue->changeBits = 0;
msgQueue->wakeMask = dwWakeMask;
QUEUE_Unlock( msgQueue );
/* Add the thread event to the handle list */
for (i = 0; i < nCount; i++) handles[i] = pHandles[i];
handles[nCount] = currTask->thdb->event;
......@@ -2058,10 +2102,14 @@ BOOL16 WINAPI InSendMessage16(void)
BOOL32 WINAPI InSendMessage32(void)
{
MESSAGEQUEUE *queue;
BOOL32 ret;
if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetFastQueue() )))
if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue() )))
return 0;
return (BOOL32)queue->InSendMessageHandle;
ret = (BOOL32)queue->InSendMessageHandle;
QUEUE_Unlock( queue );
return ret;
}
/***********************************************************************
......
......@@ -294,7 +294,7 @@ static WND* WIN_DestroyWindow( WND* wndPtr )
{
BOOL32 bPostQuit = FALSE;
WPARAM32 wQuitParam = 0;
MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
QMSG *qmsg;
while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
......@@ -306,6 +306,9 @@ static WND* WIN_DestroyWindow( WND* wndPtr )
}
QUEUE_RemoveMsg(msgQ, qmsg);
}
QUEUE_Unlock(msgQ);
/* repost WM_QUIT to make sure this app exits its message loop */
if( bPostQuit ) PostQuitMessage32(wQuitParam);
wndPtr->hmemTaskQ = 0;
......
......@@ -56,7 +56,7 @@ static HWND32 hGlobalShellWindow=0; /*the shell*/
static LPCSTR atomInternalPos;
extern MESSAGEQUEUE* pActiveQueue;
extern HQUEUE16 hActiveQueue;
/***********************************************************************
* WINPOS_CreateInternalPosAtom
......@@ -1461,7 +1461,7 @@ BOOL32 WINPOS_SetActiveWindow( HWND32 hWnd, BOOL32 fMouse, BOOL32 fChangeFocus)
* return 0;
*/
wndPtr = WIN_FindWndPtr(hWnd);
hOldActiveQueue = (pActiveQueue)?pActiveQueue->self : 0;
hOldActiveQueue = hActiveQueue;
if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
......@@ -1547,8 +1547,7 @@ BOOL32 WINPOS_SetActiveWindow( HWND32 hWnd, BOOL32 fMouse, BOOL32 fChangeFocus)
HeapFree( SystemHeap, 0, list );
}
pActiveQueue = (hNewActiveQueue)
? (MESSAGEQUEUE*) GlobalLock16(hNewActiveQueue) : NULL;
hActiveQueue = hNewActiveQueue;
if ((list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
{
......@@ -1562,6 +1561,7 @@ BOOL32 WINPOS_SetActiveWindow( HWND32 hWnd, BOOL32 fMouse, BOOL32 fChangeFocus)
}
HeapFree( SystemHeap, 0, list );
}
if (!IsWindow32(hWnd)) return 0;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment