- Changing MESSAGEQUEUE structure according to Ulrich proposition.

- One message queue for every thread needing it.
- Messages in the message queue are now stored in a linked list
- Messages are allocated in the system heap.
- Messages in the message queue are 32 bits (MSG32).
- All read/write operations regarding messages in the message queue are
  thread safe.
This commit is contained in:
Stephane Lussier 1999-01-26 09:30:05 +00:00 committed by Alexandre Julliard
parent d68d50142f
commit a4c8445ba3
4 changed files with 279 additions and 239 deletions

View File

@ -9,12 +9,17 @@
#include "wine/winuser16.h"
#include "windows.h"
#include "thread.h"
/* Message as stored in the queue (contains the extraInfo field) */
typedef struct tagQMSG
{
MSG32 msg;
DWORD extraInfo; /* Only in 3.1 */
MSG16 msg;
struct tagQMSG *nextMsg;
struct tagQMSG *prevMsg;
} QMSG;
typedef struct
@ -23,49 +28,63 @@ typedef struct
BOOL16 bPending;
} QSMCTRL;
#pragma pack(1)
/* Per-queue system windows */
typedef struct tagPERQUEUEDATA
{
HWND32 hWndCapture;
HWND32 hWndFocus;
HWND32 hWndActive;
} PERQUEUEDATA;
typedef struct tagMESSAGEQUEUE
{
HQUEUE16 next; /* 00 Next queue */
HTASK16 hTask; /* 02 hTask owning the queue */
WORD msgSize; /* 04 Size of messages in the queue */
WORD msgCount; /* 06 Number of waiting messages */
WORD nextMessage; /* 08 Next message to be retrieved */
WORD nextFreeMessage; /* 0a Next available slot in the queue */
WORD queueSize; /* 0c Size of the queue */
DWORD GetMessageTimeVal WINE_PACKED; /* 0e Value for GetMessageTime */
DWORD GetMessagePosVal WINE_PACKED; /* 12 Value for GetMessagePos */
HQUEUE16 self; /* 16 Handle to self (was: reserved) */
DWORD GetMessageExtraInfoVal; /* 18 Value for GetMessageExtraInfo */
WORD wParamHigh; /* 1c High word of wParam (was: reserved)*/
LPARAM lParam WINE_PACKED; /* 1e Next 4 values set by SendMessage */
WPARAM16 wParam; /* 22 */
UINT16 msg; /* 24 */
HWND16 hWnd; /* 26 */
DWORD SendMessageReturn; /* 28 Return value for SendMessage */
WORD wPostQMsg; /* 2c PostQuitMessage flag */
WORD wExitCode; /* 2e PostQuitMessage exit code */
WORD flags; /* 30 Queue flags */
QSMCTRL* smResultInit; /* 32 1st LRESULT ptr - was: reserved */
WORD wWinVersion; /* 36 Expected Windows version */
HQUEUE16 InSendMessageHandle; /* 38 Queue of task that sent a message */
HTASK16 hSendingTask; /* 3a Handle of task that sent a message */
HTASK16 hPrevSendingTask; /* 3c Handle of previous sender */
WORD wPaintCount; /* 3e Number of WM_PAINT needed */
WORD wTimerCount; /* 40 Number of timers for this task */
WORD changeBits; /* 42 Changed wake-up bits */
WORD wakeBits; /* 44 Queue wake-up bits */
WORD wakeMask; /* 46 Queue wake-up mask */
QSMCTRL* smResultCurrent; /* 48 ptrs to SendMessage() LRESULT - point to */
WORD SendMsgReturnPtr[1]; /* values on stack */
HANDLE16 hCurHook; /* 4e Current hook */
HANDLE16 hooks[WH_NB_HOOKS]; /* 50 Task hooks list */
QSMCTRL* smResult; /* 6c 3rd LRESULT ptr - was: reserved */
QMSG messages[1]; /* 70 Queue messages */
HQUEUE16 next; /* NNext queue */
HQUEUE16 self; /* Handle to self (was: reserved) */
THDB* thdb; /* Thread owning queue */
HANDLE32 hEvent; /* Event handle */
CRITICAL_SECTION cSection; /* Queue access critical section */
WORD flags; /* Queue flags */
WORD wWinVersion; /* Expected Windows version */
WORD msgCount; /* Number of waiting messages */
QMSG* firstMsg; /* First message in linked list */
QMSG* lastMsg; /* Last message in linked list */
WORD wPostQMsg; /* PostQuitMessage flag */
WORD wExitCode; /* PostQuitMessage exit code */
WORD wPaintCount; /* Number of WM_PAINT needed */
WORD wTimerCount; /* Number of timers for this task */
WORD changeBits; /* Changed wake-up bits */
WORD wakeBits; /* Queue wake-up bits */
WORD wakeMask; /* Queue wake-up mask */
DWORD GetMessageTimeVal; /* Value for GetMessageTime */
DWORD GetMessagePosVal; /* Value for GetMessagePos */
DWORD GetMessageExtraInfoVal; /* Value for GetMessageExtraInfo */
HQUEUE16 InSendMessageHandle; /* Queue of task that sent a message */
HTASK16 hSendingTask; /* Handle of task that sent a message */
HTASK16 hPrevSendingTask; /* Handle of previous sender */
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 hooks[WH_NB_HOOKS]; /* Task hooks list */
HANDLE16 hPerQueue; /* handle on PERQUEUEDATA structure */
} MESSAGEQUEUE;
#pragma pack(4)
/* Extra (undocumented) queue wake bits - see "Undoc. Windows" */
#define QS_SMRESULT 0x8000 /* Queue has a SendMessage() result */
@ -80,7 +99,7 @@ extern void QUEUE_WalkQueues(void);
extern BOOL32 QUEUE_IsExitingQueue( HQUEUE16 hQueue );
extern void QUEUE_SetExitingQueue( HQUEUE16 hQueue );
extern MESSAGEQUEUE *QUEUE_GetSysQueue(void);
extern void QUEUE_Signal( HTASK16 hTask );
extern void QUEUE_Signal( THDB *thdb );
extern void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit );
extern void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit );
extern void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue );
@ -89,13 +108,13 @@ extern void QUEUE_IncPaintCount( HQUEUE16 hQueue );
extern void QUEUE_DecPaintCount( HQUEUE16 hQueue );
extern void QUEUE_IncTimerCount( HQUEUE16 hQueue );
extern void QUEUE_DecTimerCount( HQUEUE16 hQueue );
extern BOOL32 QUEUE_CreateSysMsgQueue( int size );
extern BOOL32 QUEUE_CreateSysMsgQueue( );
extern BOOL32 QUEUE_DeleteMsgQueue( HQUEUE16 hQueue );
extern HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue );
extern BOOL32 QUEUE_AddMsg( HQUEUE16 hQueue, MSG16 * msg, DWORD extraInfo );
extern int QUEUE_FindMsg( MESSAGEQUEUE * msgQueue, HWND32 hwnd,
extern BOOL32 QUEUE_AddMsg( HQUEUE16 hQueue, MSG32 * msg, DWORD extraInfo );
extern QMSG* QUEUE_FindMsg( MESSAGEQUEUE * msgQueue, HWND32 hwnd,
int first, int last );
extern void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, int pos );
extern void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, QMSG *qmsg );
extern void QUEUE_FlushMessages(HQUEUE16);
extern void hardware_event( WORD message, WORD wParam, LONG lParam,
int xPos, int yPos, DWORD time, DWORD extraInfo );

View File

@ -441,9 +441,12 @@ static int MSG_JournalPlayBackMsg(void)
static BOOL32 MSG_PeekHardwareMsg( MSG16 *msg, HWND16 hwnd, DWORD filter,
BOOL32 remove )
{
/* FIXME: should deal with MSG32 instead of MSG16 */
DWORD status = SYSQ_MSG_ACCEPT;
MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
int i, kbd_msg, pos = sysMsgQueue->nextMessage;
int kbd_msg;
QMSG *nextqmsg, *qmsg = sysMsgQueue->firstMsg;
/* FIXME: there has to be a better way to do this */
joySendMessages();
@ -453,16 +456,20 @@ static BOOL32 MSG_PeekHardwareMsg( MSG16 *msg, HWND16 hwnd, DWORD filter,
&& EVENT_Pending())
EVENT_WaitNetEvent( FALSE, FALSE );
for (i = kbd_msg = 0; i < sysMsgQueue->msgCount; i++, pos++)
for ( kbd_msg = 0; qmsg; qmsg = nextqmsg)
{
if (pos >= sysMsgQueue->queueSize) pos = 0;
*msg = sysMsgQueue->messages[pos].msg;
/* FIXME: this line will be reenabled when msg will be a MSG32 */
/* *msg = qmsg->msg; */
STRUCT32_MSG32to16(&qmsg->msg, msg);
nextqmsg = qmsg->nextMsg;
/* Translate message */
if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST))
{
HWND32 hWndScope = (HWND32)sysMsgQueue->messages[pos].extraInfo;
HWND32 hWndScope = (HWND32)qmsg->extraInfo;
status = MSG_TranslateMouseMsg(hwnd, filter, msg, remove,
(Options.managed && IsWindow32(hWndScope) )
@ -490,7 +497,7 @@ static BOOL32 MSG_PeekHardwareMsg( MSG16 *msg, HWND16 hwnd, DWORD filter,
SEGPTR_FREE(hook);
if (ret)
{
QUEUE_RemoveMsg( sysMsgQueue, pos );
QUEUE_RemoveMsg( sysMsgQueue, qmsg );
continue;
}
status = SYSQ_MSG_ACCEPT;
@ -525,7 +532,7 @@ static BOOL32 MSG_PeekHardwareMsg( MSG16 *msg, HWND16 hwnd, DWORD filter,
}
if (remove)
QUEUE_RemoveMsg( sysMsgQueue, pos );
QUEUE_RemoveMsg( sysMsgQueue, qmsg );
/* continue */
case SYSQ_MSG_CONTINUE:
@ -538,7 +545,7 @@ static BOOL32 MSG_PeekHardwareMsg( MSG16 *msg, HWND16 hwnd, DWORD filter,
if (remove)
{
if (HOOK_IsHooked( WH_JOURNALRECORD )) MSG_JournalRecordMsg( msg );
QUEUE_RemoveMsg( sysMsgQueue, pos );
QUEUE_RemoveMsg( sysMsgQueue, qmsg );
}
return TRUE;
}
@ -546,6 +553,7 @@ static BOOL32 MSG_PeekHardwareMsg( MSG16 *msg, HWND16 hwnd, DWORD filter,
}
/**********************************************************************
* SetDoubleClickTime16 (USER.20)
*/
@ -611,11 +619,9 @@ static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND16 hwnd, UINT16 msg,
}
/* resume sending */
queue->hWnd = hwnd;
queue->msg = msg;
queue->wParam = LOWORD(wParam);
queue->wParamHigh = HIWORD(wParam);
queue->hWnd32 = hwnd;
queue->msg32 = msg;
queue->wParam32 = wParam;
queue->lParam = lParam;
queue->hPrevSendingTask = destQ->hSendingTask;
destQ->hSendingTask = GetFastQueue();
@ -635,7 +641,8 @@ static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND16 hwnd, UINT16 msg,
{
if (!(queue->wakeBits & QS_SMRESULT))
{
if (THREAD_IsWin16( THREAD_Current() )) DirectedYield( destQ->hTask );
if (THREAD_IsWin16( THREAD_Current() ))
DirectedYield( destQ->thdb->teb.htask16 );
QUEUE_WaitBits( QS_SMRESULT );
TRACE(sendmsg,"\tsm: have result!\n");
}
@ -675,8 +682,8 @@ void WINAPI ReplyMessage16( LRESULT result )
while( (senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->InSendMessageHandle)))
{
TRACE(msg,"\trpm: replying to %04x (%04x -> %04x)\n",
queue->msg, queue->self, senderQ->self);
TRACE(msg,"\trpm: replying to %08x (%04x -> %04x)\n",
queue->msg32, queue->self, senderQ->self);
if( queue->wakeBits & QS_SENDMESSAGE )
{
@ -697,7 +704,8 @@ void WINAPI ReplyMessage16( LRESULT result )
queue->InSendMessageHandle = 0;
QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
if (THREAD_IsWin16(THREAD_Current())) DirectedYield( senderQ->hTask );
if (THREAD_IsWin16( THREAD_Current() ))
DirectedYield( senderQ->thdb->teb.htask16 );
}
@ -707,7 +715,7 @@ void WINAPI ReplyMessage16( LRESULT result )
static BOOL32 MSG_PeekMessage( LPMSG16 msg, HWND16 hwnd, WORD first, WORD last,
WORD flags, BOOL32 peek )
{
int pos, mask;
int mask;
MESSAGEQUEUE *msgQueue;
HQUEUE16 hQueue;
@ -735,6 +743,8 @@ static BOOL32 MSG_PeekMessage( LPMSG16 msg, HWND16 hwnd, WORD first, WORD last,
while(1)
{
QMSG *qmsg;
hQueue = GetFastQueue();
msgQueue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
if (!msgQueue) return FALSE;
@ -762,15 +772,17 @@ static BOOL32 MSG_PeekMessage( LPMSG16 msg, HWND16 hwnd, WORD first, WORD last,
/* Now find a normal message */
if (((msgQueue->wakeBits & mask) & QS_POSTMESSAGE) &&
((pos = QUEUE_FindMsg( msgQueue, hwnd, first, last )) != -1))
((qmsg = QUEUE_FindMsg( msgQueue, hwnd, first, last )) != 0))
{
QMSG *qmsg = &msgQueue->messages[pos];
*msg = qmsg->msg;
/* FIXME: this line will be reenabled when msg will be a MSG32 */
/* *msg = qmsg->msg; */
STRUCT32_MSG32to16(&qmsg->msg, msg);
msgQueue->GetMessageTimeVal = msg->time;
msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
if (flags & PM_REMOVE) QUEUE_RemoveMsg( msgQueue, pos );
if (flags & PM_REMOVE) QUEUE_RemoveMsg( msgQueue, qmsg );
break;
}
@ -1129,7 +1141,7 @@ BOOL32 WINAPI GetMessage32W(
BOOL16 WINAPI PostMessage16( HWND16 hwnd, UINT16 message, WPARAM16 wParam,
LPARAM lParam )
{
MSG16 msg;
MSG32 msg;
WND *wndPtr;
msg.hwnd = hwnd;
@ -1204,7 +1216,7 @@ BOOL32 WINAPI PostMessage32W( HWND32 hwnd, UINT32 message, WPARAM32 wParam,
BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 message, WPARAM16 wParam,
LPARAM lParam )
{
MSG16 msg;
MSG32 msg;
if (GetTaskQueue(hTask) == 0) return FALSE;
msg.hwnd = 0;

View File

@ -39,28 +39,27 @@ void QUEUE_DumpQueue( HQUEUE16 hQueue )
MESSAGEQUEUE *pq;
if (!(pq = (MESSAGEQUEUE*) GlobalLock16( hQueue )) ||
GlobalSize16(hQueue) < sizeof(MESSAGEQUEUE)+pq->queueSize*sizeof(QMSG))
GlobalSize16(hQueue) != sizeof(MESSAGEQUEUE))
{
WARN(msg, "%04x is not a queue handle\n", hQueue );
return;
}
DUMP( "next: %12.4x Intertask SendMessage:\n"
"hTask: %11.4x ----------------------\n"
"msgSize: %9.4x hWnd: %10.4x\n"
"msgCount: %8.4x msg: %11.4x\n"
"msgNext: %9.4x wParam: %8.4x\n"
"msgFree: %9.4x lParam: %8.8x\n"
"qSize: %11.4x lRet: %10.8x\n"
"thread: %10p ----------------------\n"
"hWnd: %12.8x\n"
"firstMsg: %8p lastMsg: %8p"
"msgCount: %8.4x msg: %11.8x\n"
"wParam: %10.8x lParam: %8.8x\n"
"lRet: %12.8x\n"
"wWinVer: %9.4x ISMH: %10.4x\n"
"paints: %10.4x hSendTask: %5.4x\n"
"timers: %10.4x hPrevSend: %5.4x\n"
"wakeBits: %8.4x\n"
"wakeMask: %8.4x\n"
"hCurHook: %8.4x\n",
pq->next, pq->hTask, pq->msgSize, pq->hWnd,
pq->msgCount, pq->msg, pq->nextMessage, pq->wParam,
pq->nextFreeMessage, (unsigned)pq->lParam, pq->queueSize,
pq->next, pq->thdb, pq->hWnd32, pq->firstMsg, pq->lastMsg,
pq->msgCount, pq->msg32, pq->wParam32,(unsigned)pq->lParam,
(unsigned)pq->SendMessageReturn, pq->wWinVersion, pq->InSendMessageHandle,
pq->wPaintCount, pq->hSendingTask, pq->wTimerCount,
pq->hPrevSendingTask, pq->wakeBits, pq->wakeMask, pq->hCurHook);
@ -75,7 +74,7 @@ void QUEUE_WalkQueues(void)
char module[10];
HQUEUE16 hQueue = hFirstQueue;
DUMP( "Queue Size Msgs Task\n" );
DUMP( "Queue Msgs Thread Task Module\n" );
while (hQueue)
{
MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
@ -84,10 +83,10 @@ void QUEUE_WalkQueues(void)
WARN( msg, "Bad queue handle %04x\n", hQueue );
return;
}
if (!GetModuleName( queue->hTask, module, sizeof(module )))
if (!GetModuleName( queue->thdb->process->task, module, sizeof(module )))
strcpy( module, "???" );
DUMP( "%04x %5d %4d %04x %s\n", hQueue, queue->msgSize,
queue->msgCount, queue->hTask, module );
DUMP( "%04x %4d %p %04x %s\n", hQueue,queue->msgCount,
queue->thdb, queue->thdb->process->task, module );
hQueue = queue->next;
}
DUMP( "\n" );
@ -117,25 +116,25 @@ void QUEUE_SetExitingQueue( HQUEUE16 hQueue )
*
* Creates a message queue. Doesn't link it into queue list!
*/
static HQUEUE16 QUEUE_CreateMsgQueue( int size )
static HQUEUE16 QUEUE_CreateMsgQueue( )
{
HQUEUE16 hQueue;
MESSAGEQUEUE * msgQueue;
int queueSize;
TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
TRACE(msg,"Creating message queue...\n");
queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
if (!(hQueue = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, queueSize )))
if (!(hQueue = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT,
sizeof(MESSAGEQUEUE) )))
{
return 0;
}
msgQueue = (MESSAGEQUEUE *) GlobalLock16( hQueue );
InitializeCriticalSection( &msgQueue->cSection );
msgQueue->self = hQueue;
msgQueue->msgSize = sizeof(QMSG);
msgQueue->queueSize = size;
msgQueue->wakeBits = msgQueue->changeBits = QS_SMPARAMSFREE;
msgQueue->wWinVersion = pTask ? pTask->version : 0;
GlobalUnlock16( hQueue );
return hQueue;
}
@ -201,9 +200,7 @@ BOOL32 QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
*/
BOOL32 QUEUE_CreateSysMsgQueue( int size )
{
if (size > MAX_QUEUE_SIZE) size = MAX_QUEUE_SIZE;
else if (size <= 0) size = 1;
if (!(hmemSysMsgQueue = QUEUE_CreateMsgQueue( size ))) return FALSE;
if (!(hmemSysMsgQueue = QUEUE_CreateMsgQueue( ))) return FALSE;
sysMsgQueue = (MESSAGEQUEUE *) GlobalLock16( hmemSysMsgQueue );
return TRUE;
}
@ -220,18 +217,12 @@ MESSAGEQUEUE *QUEUE_GetSysQueue(void)
/***********************************************************************
* QUEUE_Signal
*/
void QUEUE_Signal( HTASK16 hTask )
void QUEUE_Signal( THDB *thdb )
{
PDB32 *pdb;
THREAD_ENTRY *entry;
TDB *pTask = (TDB *)GlobalLock16( hTask );
if ( !pTask ) return;
/* Wake up thread waiting for message */
SetEvent( pTask->thdb->event );
SetEvent( thdb->event );
PostEvent( hTask );
PostEvent( thdb->process->task );
}
/***********************************************************************
@ -250,7 +241,7 @@ static void QUEUE_Wait( DWORD wait_mask )
/***********************************************************************
* QUEUE_SetWakeBit
* QUEUE_SetWakeBit `
*
* See "Windows Internals", p.449
*/
@ -266,7 +257,7 @@ void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit )
if (queue->wakeMask & bit)
{
queue->wakeMask = 0;
QUEUE_Signal( queue->hTask );
QUEUE_Signal( queue->thdb );
}
}
@ -354,33 +345,34 @@ void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue )
(unsigned)queue->smResultCurrent, (unsigned)prevCtrlPtr );
QUEUE_SetWakeBit( senderQ, QS_SMPARAMSFREE );
TRACE(msg, "\trcm: calling wndproc - %04x %04x %04x%04x %08x\n",
senderQ->hWnd, senderQ->msg, senderQ->wParamHigh,
senderQ->wParam, (unsigned)senderQ->lParam );
TRACE(msg, "\trcm: calling wndproc - %08x %08x %08x %08x\n",
senderQ->hWnd32, senderQ->msg32,
senderQ->wParam32, (unsigned)senderQ->lParam );
if (IsWindow32( senderQ->hWnd ))
if (IsWindow32( senderQ->hWnd32 ))
{
WND *wndPtr = WIN_FindWndPtr( senderQ->hWnd );
WND *wndPtr = WIN_FindWndPtr( senderQ->hWnd32 );
DWORD extraInfo = queue->GetMessageExtraInfoVal;
queue->GetMessageExtraInfoVal = senderQ->GetMessageExtraInfoVal;
if (senderQ->flags & QUEUE_SM_WIN32)
{
WPARAM32 wParam = MAKELONG( senderQ->wParam, senderQ->wParamHigh );
TRACE(msg, "\trcm: msg is Win32\n" );
if (senderQ->flags & QUEUE_SM_UNICODE)
result = CallWindowProc32W( wndPtr->winproc,
senderQ->hWnd, senderQ->msg,
wParam, senderQ->lParam );
senderQ->hWnd32, senderQ->msg32,
senderQ->wParam32, senderQ->lParam );
else
result = CallWindowProc32A( wndPtr->winproc,
senderQ->hWnd, senderQ->msg,
wParam, senderQ->lParam );
senderQ->hWnd32, senderQ->msg32,
senderQ->wParam32, senderQ->lParam );
}
else /* Win16 message */
result = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
senderQ->hWnd, senderQ->msg,
senderQ->wParam, senderQ->lParam );
(HWND16) senderQ->hWnd32,
(UINT16) senderQ->msg32,
LOWORD (senderQ->wParam32),
senderQ->lParam );
queue->GetMessageExtraInfoVal = extraInfo; /* Restore extra info */
TRACE(msg,"\trcm: result = %08x\n", (unsigned)result );
@ -443,97 +435,115 @@ void QUEUE_FlushMessages( HQUEUE16 hQueue )
*
* Add a message to the queue. Return FALSE if queue is full.
*/
BOOL32 QUEUE_AddMsg( HQUEUE16 hQueue, MSG16 * msg, DWORD extraInfo )
BOOL32 QUEUE_AddMsg( HQUEUE16 hQueue, MSG32 *msg, DWORD extraInfo )
{
int pos;
MESSAGEQUEUE *msgQueue;
QMSG *qmsg;
SIGNAL_MaskAsyncEvents( TRUE );
if (!(msgQueue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return FALSE;
pos = msgQueue->nextFreeMessage;
/* Check if queue is full */
if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0))
{
SIGNAL_MaskAsyncEvents( FALSE );
WARN( msg,"Queue is full!\n" );
return FALSE;
}
/* allocate new message in global heap for now */
if (!(qmsg = (QMSG *) HeapAlloc( SystemHeap, 0, sizeof(QMSG) ) ))
return 0;
EnterCriticalSection( &msgQueue->cSection );
/* Store message */
msgQueue->messages[pos].msg = *msg;
msgQueue->messages[pos].extraInfo = extraInfo;
if (pos < msgQueue->queueSize-1) pos++;
else pos = 0;
msgQueue->nextFreeMessage = pos;
qmsg->msg = *msg;
qmsg->extraInfo = extraInfo;
/* insert the message in the link list */
qmsg->nextMsg = 0;
qmsg->prevMsg = msgQueue->lastMsg;
if (msgQueue->lastMsg)
msgQueue->lastMsg->nextMsg = qmsg;
/* update first and last anchor in message queue */
msgQueue->lastMsg = qmsg;
if (!msgQueue->firstMsg)
msgQueue->firstMsg = qmsg;
msgQueue->msgCount++;
SIGNAL_MaskAsyncEvents( FALSE );
LeaveCriticalSection( &msgQueue->cSection );
QUEUE_SetWakeBit( msgQueue, QS_POSTMESSAGE );
return TRUE;
}
/***********************************************************************
* QUEUE_FindMsg
*
* Find a message matching the given parameters. Return -1 if none available.
*/
int QUEUE_FindMsg( MESSAGEQUEUE * msgQueue, HWND32 hwnd, int first, int last )
QMSG* QUEUE_FindMsg( MESSAGEQUEUE * msgQueue, HWND32 hwnd, int first, int last )
{
int i, pos = msgQueue->nextMessage;
QMSG* qmsg;
TRACE(msg,"hwnd=%04x pos=%d\n", hwnd, pos );
EnterCriticalSection( &msgQueue->cSection );
if (!msgQueue->msgCount) return -1;
if (!hwnd && !first && !last) return pos;
for (i = 0; i < msgQueue->msgCount; i++)
if (!msgQueue->msgCount)
qmsg = 0;
else if (!hwnd && !first && !last)
qmsg = msgQueue->firstMsg;
else
{
MSG16 * msg = &msgQueue->messages[pos].msg;
/* look in linked list for message matching first and last criteria */
for (qmsg = msgQueue->firstMsg; qmsg; qmsg = qmsg->nextMsg)
{
MSG32 *msg = &(qmsg->msg);
if (!hwnd || (msg->hwnd == hwnd))
{
if (!first && !last) return pos;
if ((msg->message >= first) && (msg->message <= last)) return pos;
if (!first && !last)
break; /* found it */
if ((msg->message >= first) && (msg->message <= last))
break; /* found it */
}
}
if (pos < msgQueue->queueSize-1) pos++;
else pos = 0;
}
return -1;
LeaveCriticalSection( &msgQueue->cSection );
return qmsg;
}
/***********************************************************************
* QUEUE_RemoveMsg
*
* Remove a message from the queue (pos must be a valid position).
*/
void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, int pos )
void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, QMSG *qmsg )
{
SIGNAL_MaskAsyncEvents( TRUE );
EnterCriticalSection( &msgQueue->cSection );
if (pos >= msgQueue->nextMessage)
{
for ( ; pos > msgQueue->nextMessage; pos--)
msgQueue->messages[pos] = msgQueue->messages[pos-1];
msgQueue->nextMessage++;
if (msgQueue->nextMessage >= msgQueue->queueSize)
msgQueue->nextMessage = 0;
}
else
{
for ( ; pos < msgQueue->nextFreeMessage; pos++)
msgQueue->messages[pos] = msgQueue->messages[pos+1];
if (msgQueue->nextFreeMessage) msgQueue->nextFreeMessage--;
else msgQueue->nextFreeMessage = msgQueue->queueSize-1;
}
/* set the linked list */
if (qmsg->prevMsg)
qmsg->prevMsg->nextMsg = qmsg->nextMsg;
if (qmsg->nextMsg)
qmsg->nextMsg->prevMsg = qmsg->prevMsg;
if (msgQueue->firstMsg == qmsg)
msgQueue->firstMsg = qmsg->nextMsg;
if (msgQueue->lastMsg == qmsg)
msgQueue->lastMsg = qmsg->prevMsg;
/* deallocate the memory for the message */
HeapFree( SystemHeap, 0, qmsg );
msgQueue->msgCount--;
if (!msgQueue->msgCount) msgQueue->wakeBits &= ~QS_POSTMESSAGE;
SIGNAL_MaskAsyncEvents( FALSE );
LeaveCriticalSection( &msgQueue->cSection );
}
@ -594,49 +604,62 @@ static void QUEUE_WakeSomeone( UINT32 message )
void hardware_event( WORD message, WORD wParam, LONG lParam,
int xPos, int yPos, DWORD time, DWORD extraInfo )
{
MSG16 *msg;
int pos;
MSG32 *msg;
QMSG *qmsg = sysMsgQueue->lastMsg;
int mergeMsg = 0;
if (!sysMsgQueue) return;
pos = sysMsgQueue->nextFreeMessage;
/* Merge with previous event if possible */
if ((message == WM_MOUSEMOVE) && sysMsgQueue->msgCount)
if ((message == WM_MOUSEMOVE) && sysMsgQueue->lastMsg)
{
if (pos > 0) pos--;
else pos = sysMsgQueue->queueSize - 1;
msg = &sysMsgQueue->messages[pos].msg;
msg = &(sysMsgQueue->lastMsg->msg);
if ((msg->message == message) && (msg->wParam == wParam))
sysMsgQueue->msgCount--; /* Merge events */
else
pos = sysMsgQueue->nextFreeMessage; /* Don't merge */
{
/* Merge events */
qmsg = sysMsgQueue->lastMsg;
mergeMsg = 1;
}
}
/* Check if queue is full */
if ((pos == sysMsgQueue->nextMessage) && sysMsgQueue->msgCount)
if (!mergeMsg)
{
/* Queue is full, beep (but not on every mouse motion...) */
if (message != WM_MOUSEMOVE) MessageBeep32(0);
/* Should I limit the number of message in
the system message queue??? */
/* Don't merge allocate a new msg in the global heap */
if (!(qmsg = (QMSG *) HeapAlloc( SystemHeap, 0, sizeof(QMSG) ) ))
return;
/* put message at the end of the linked list */
qmsg->nextMsg = 0;
qmsg->prevMsg = sysMsgQueue->lastMsg;
if (sysMsgQueue->lastMsg)
sysMsgQueue->lastMsg->nextMsg = qmsg;
/* set last and first anchor index in system message queue */
sysMsgQueue->lastMsg = qmsg;
if (!sysMsgQueue->firstMsg)
sysMsgQueue->firstMsg = qmsg;
sysMsgQueue->msgCount++;
}
/* Store message */
msg = &sysMsgQueue->messages[pos].msg;
msg = &(qmsg->msg);
msg->hwnd = 0;
msg->message = message;
msg->wParam = wParam;
msg->lParam = lParam;
msg->time = time;
msg->pt.x = xPos & 0xffff;
msg->pt.y = yPos & 0xffff;
sysMsgQueue->messages[pos].extraInfo = extraInfo;
if (pos < sysMsgQueue->queueSize - 1) pos++;
else pos = 0;
sysMsgQueue->nextFreeMessage = pos;
sysMsgQueue->msgCount++;
msg->pt.x = xPos;
msg->pt.y = yPos;
qmsg->extraInfo = extraInfo;
QUEUE_WakeSomeone( message );
}
@ -647,7 +670,7 @@ void hardware_event( WORD message, WORD wParam, LONG lParam,
HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue )
{
MESSAGEQUEUE *queue = GlobalLock16( hQueue );
return (queue) ? queue->hTask : 0 ;
return (queue) ? queue->thdb->process->task : 0 ;
}
@ -780,45 +803,12 @@ BOOL16 WINAPI SetMessageQueue16( INT16 size )
*/
BOOL32 WINAPI SetMessageQueue32( INT32 size )
{
HQUEUE16 hQueue, hNewQueue;
MESSAGEQUEUE *queuePtr;
/* now obsolete the message queue will be expanded dynamically
as necessary */
TRACE(msg,"task %04x size %i\n", GetCurrentTask(), size);
/* access the queue to create it if it's not existing */
GetFastQueue();
if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return FALSE;
if( !(hNewQueue = QUEUE_CreateMsgQueue( size )))
{
WARN(msg, "failed!\n");
return FALSE;
}
queuePtr = (MESSAGEQUEUE *)GlobalLock16( hNewQueue );
SIGNAL_MaskAsyncEvents( TRUE );
/* Copy data and free the old message queue */
if ((hQueue = GetThreadQueue(0)) != 0)
{
MESSAGEQUEUE *oldQ = (MESSAGEQUEUE *)GlobalLock16( hQueue );
memcpy( &queuePtr->wParamHigh, &oldQ->wParamHigh,
(int)oldQ->messages - (int)(&oldQ->wParamHigh) );
HOOK_ResetQueueHooks( hNewQueue );
if( WIN_GetDesktop()->hmemTaskQ == hQueue )
WIN_GetDesktop()->hmemTaskQ = hNewQueue;
WIN_ResetQueueWindows( WIN_GetDesktop(), hQueue, hNewQueue );
CLIPBOARD_ResetLock( hQueue, hNewQueue );
QUEUE_DeleteMsgQueue( hQueue );
}
/* Link new queue into list */
queuePtr->hTask = GetCurrentTask();
queuePtr->next = hFirstQueue;
hFirstQueue = hNewQueue;
if( !queuePtr->next ) pCursorQueue = queuePtr;
SetThreadQueue( 0, hNewQueue );
SIGNAL_MaskAsyncEvents( FALSE );
return TRUE;
}
@ -827,19 +817,38 @@ BOOL32 WINAPI SetMessageQueue32( INT32 size )
*/
HQUEUE16 WINAPI InitThreadInput( WORD unknown, WORD flags )
{
HQUEUE16 hQueue = GetTaskQueue( 0 );
HQUEUE16 hQueue;
MESSAGEQUEUE *queuePtr;
THDB *thdb = THREAD_Current();
if (!thdb)
return 0;
hQueue = thdb->teb.queue;
if ( !hQueue )
{
/* Create task message queue */
int queueSize = GetProfileInt32A( "windows", "DefaultQueueSize", 8 );
SetMessageQueue32( queueSize );
return GetTaskQueue( 0 );
/* Create thread message queue */
if( !(hQueue = QUEUE_CreateMsgQueue( 0 )))
{
WARN(msg, "failed!\n");
return FALSE;
}
/* Link new queue into list */
queuePtr = (MESSAGEQUEUE *)GlobalLock16( hQueue );
queuePtr->thdb = THREAD_Current();
SIGNAL_MaskAsyncEvents( TRUE );
SetThreadQueue( 0, hQueue );
thdb->teb.queue = hQueue;
queuePtr->next = hFirstQueue;
hFirstQueue = hQueue;
SIGNAL_MaskAsyncEvents( FALSE );
}
FIXME( msg, "(%04X,%04X): should create thread-local message queue!\n",
unknown, flags );
SetFastQueue( 0, hQueue );
return hQueue;
}

View File

@ -292,19 +292,19 @@ static WND* WIN_DestroyWindow( WND* wndPtr )
if( wndPtr->hmemTaskQ )
{
int pos;
BOOL32 bPostQuit = FALSE;
WPARAM32 wQuitParam = 0;
MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
QMSG *qmsg;
while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
{
if( msgQ->messages[pos].msg.message == WM_QUIT )
if( qmsg->msg.message == WM_QUIT )
{
bPostQuit = TRUE;
wQuitParam = msgQ->messages[pos].msg.wParam;
wQuitParam = qmsg->msg.wParam;
}
QUEUE_RemoveMsg(msgQ, pos);
QUEUE_RemoveMsg(msgQ, qmsg);
}
/* repost WM_QUIT to make sure this app exits its message loop */
if( bPostQuit ) PostQuitMessage32(wQuitParam);