diff --git a/include/queue.h b/include/queue.h index 73e1ee67750..3c0107e8b47 100644 --- a/include/queue.h +++ b/include/queue.h @@ -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 ); diff --git a/windows/message.c b/windows/message.c index 7976502a47d..db9ea244184 100644 --- a/windows/message.c +++ b/windows/message.c @@ -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; diff --git a/windows/queue.c b/windows/queue.c index f83647acb9e..ff3ff13f01d 100644 --- a/windows/queue.c +++ b/windows/queue.c @@ -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; } diff --git a/windows/win.c b/windows/win.c index 8dd6e3f3f35..5ac563c9f92 100644 --- a/windows/win.c +++ b/windows/win.c @@ -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);