Author: jimtabor Date: Tue Nov 3 15:18:51 2015 New Revision: 69793
URL: http://svn.reactos.org/svn/reactos?rev=69793&view=rev Log: [Win32SS] - Simplify and restructure thread send messages, use look aside list, message signals and global message link for sorting trouble messages. - See CORE-9210 for more information. Related to and fixed CORE-9718 and CORE-9975. Could have fixed CORE-9695.
Modified: trunk/reactos/win32ss/user/ntuser/callback.c trunk/reactos/win32ss/user/ntuser/focus.c trunk/reactos/win32ss/user/ntuser/main.c trunk/reactos/win32ss/user/ntuser/message.c trunk/reactos/win32ss/user/ntuser/msgqueue.c trunk/reactos/win32ss/user/ntuser/msgqueue.h trunk/reactos/win32ss/user/ntuser/win32.h
Modified: trunk/reactos/win32ss/user/ntuser/callback.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/callbac... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/callback.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/callback.c [iso-8859-1] Tue Nov 3 15:18:51 2015 @@ -51,12 +51,18 @@ PINT_CALLBACK_HEADER Mem; PTHREADINFO W32Thread;
- ASSERT(Data); - - Mem = ((PINT_CALLBACK_HEADER)Data - 1); - W32Thread = PsGetCurrentThreadWin32Thread(); ASSERT(W32Thread); + + if (W32Thread->TIF_flags & TIF_INCLEANUP) + { + ERR("CbFM Thread is already in cleanup\n"); + return; + } + + ASSERT(Data); + + Mem = ((PINT_CALLBACK_HEADER)Data - 1);
/* Remove the memory block from the thread's callback list */ RemoveEntryList(&Mem->ListEntry); @@ -340,8 +346,9 @@ &ResultLength); if (!NT_SUCCESS(Status)) { + ERR("Error Callback to User space Status %lx\n",Status); UserEnterCo(); - return -1; + return 0; }
_SEH2_TRY
Modified: trunk/reactos/win32ss/user/ntuser/focus.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/focus.c... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/focus.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/focus.c [iso-8859-1] Tue Nov 3 15:18:51 2015 @@ -340,7 +340,13 @@ WARN("ASYNC SAW: Found one in the Sent Msg Queue! %p Activate/Deactivate %d\n", Message->Msg.hwnd, !!wParam); RemoveEntryList(&Message->ListEntry); // Purge the entry. ClearMsgBitsMask(pti, Message->QS_Flags); - ExFreePoolWithTag(Message, TAG_USRMSG); + InsertTailList(&usmList, &Message->ListEntry); + /* Notify the sender. */ + if (Message->pkCompletionEvent != NULL) + { + KeSetEvent(Message->pkCompletionEvent, IO_NO_INCREMENT, FALSE); + } + FreeUserMessage(Message); } } } @@ -929,7 +935,7 @@ { if (Window->head.pti->MessageQueue != ThreadQueue) { - ERR("Window Thread dos not match Current!\n"); + ERR("Window Thread does not match Current!\n"); return NULL; } }
Modified: trunk/reactos/win32ss/user/ntuser/main.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/main.c?... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/main.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/main.c [iso-8859-1] Tue Nov 3 15:18:51 2015 @@ -488,8 +488,6 @@ InitializeListHead(&ptiCurrent->W32CallbackListHead); InitializeListHead(&ptiCurrent->PostedMessagesListHead); InitializeListHead(&ptiCurrent->SentMessagesListHead); - InitializeListHead(&ptiCurrent->DispatchingMessagesHead); - InitializeListHead(&ptiCurrent->LocalDispatchingMessagesHead); InitializeListHead(&ptiCurrent->PtiLink); for (i = 0; i < NB_HOOKS; i++) { @@ -776,6 +774,12 @@
psle = PopEntryList(&ptiCurrent->ReferencesList); } + } + + if (ptiCurrent->cEnterCount) + { + KeSetKernelStackSwapEnable(TRUE); + ptiCurrent->cEnterCount = 0; }
/* Find the THREADINFO in the PROCESSINFO's list */
Modified: trunk/reactos/win32ss/user/ntuser/message.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/message... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/message.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/message.c [iso-8859-1] Tue Nov 3 15:18:51 2015 @@ -1278,7 +1278,7 @@ LPARAM lParam ) { ULONG_PTR Result = 0; - if(co_IntSendMessageTimeout(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result)) + if (co_IntSendMessageTimeout(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result)) { return (LRESULT)Result; } @@ -1399,7 +1399,7 @@ wParam, lParamPacked, lParamBufferSize ); - if(uResult) + if (uResult) { *uResult = Result; } @@ -1697,7 +1697,7 @@ RETURN(TRUE); }
- if(!(Message = ExAllocatePoolWithTag(NonPagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG))) + if(!(Message = AllocateUserMessage(FALSE))) { ERR("MsqSendMessage(): Not enough memory to allocate a message"); RETURN( FALSE); @@ -1707,19 +1707,18 @@ Message->Msg.message = Msg; Message->Msg.wParam = wParam; Message->Msg.lParam = lParamPacked; - Message->CompletionEvent = NULL; - Message->Result = 0; + Message->pkCompletionEvent = NULL; // No event needed. Message->lResult = 0; Message->QS_Flags = 0; Message->ptiReceiver = ptiSendTo; Message->ptiSender = NULL; // mjmartin, you are right! This is null. Message->ptiCallBackSender = Win32Thread; - InitializeListHead(&Message->DispatchingListEntry); Message->CompletionCallback = CompletionCallback; Message->CompletionCallbackContext = CompletionCallbackContext; Message->HookMessage = MSQ_NORMAL; Message->HasPackedLParam = (lParamBufferSize > 0); Message->QS_Flags = QS_SENDMESSAGE; + Message->flags = SMF_RECEIVERFREE;
if (Msg & 0x80000000) // Higher priority event message! InsertHeadList(&ptiSendTo->SentMessagesListHead, &Message->ListEntry); @@ -2723,14 +2722,15 @@ break; case FNID_SENDMESSAGE: { - Ret = co_IntDoSendMessage(hWnd, Msg, wParam, lParam, 0); + lResult = co_IntDoSendMessage(hWnd, Msg, wParam, lParam, 0); + Ret = TRUE;
if (ResultInfo) { _SEH2_TRY { ProbeForWrite((PVOID)ResultInfo, sizeof(ULONG_PTR), 1); - RtlCopyMemory((PVOID)ResultInfo, &Ret, sizeof(ULONG_PTR)); + RtlCopyMemory((PVOID)ResultInfo, &lResult, sizeof(ULONG_PTR)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
Modified: trunk/reactos/win32ss/user/ntuser/msgqueue.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/msgqueu... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/msgqueue.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/msgqueue.c [iso-8859-1] Tue Nov 3 15:18:51 2015 @@ -14,10 +14,12 @@ /* GLOBALS *******************************************************************/
static PPAGED_LOOKASIDE_LIST pgMessageLookasideList; +static PPAGED_LOOKASIDE_LIST pgSendMsgLookasideList; +INT SendMsgCount = 0; PUSER_MESSAGE_QUEUE gpqCursor; ULONG_PTR gdwMouseMoveExtraInfo = 0; DWORD gdwMouseMoveTimeStamp = 0; - +LIST_ENTRY usmList;
/* FUNCTIONS *****************************************************************/
@@ -26,6 +28,7 @@ NTAPI MsqInitializeImpl(VOID) { + // Setup Post Messages pgMessageLookasideList = ExAllocatePoolWithTag(NonPagedPool, sizeof(PAGED_LOOKASIDE_LIST), TAG_USRMSG); if (!pgMessageLookasideList) return STATUS_NO_MEMORY; @@ -36,6 +39,19 @@ sizeof(USER_MESSAGE), TAG_USRMSG, 256); + // Setup Send Messages + pgSendMsgLookasideList = ExAllocatePoolWithTag(NonPagedPool, sizeof(PAGED_LOOKASIDE_LIST), TAG_USRMSG); + if (!pgSendMsgLookasideList) + return STATUS_NO_MEMORY; + ExInitializePagedLookasideList(pgSendMsgLookasideList, + NULL, + NULL, + 0, + sizeof(USER_SENT_MESSAGE), + TAG_USRMSG, + 16); + + InitializeListHead(&usmList);
return(STATUS_SUCCESS); } @@ -743,6 +759,115 @@ ExFreeToPagedLookasideList(pgMessageLookasideList, Message); }
+PUSER_SENT_MESSAGE FASTCALL +AllocateUserMessage(BOOL KEvent) +{ + PUSER_SENT_MESSAGE Message; + + if(!(Message = ExAllocateFromPagedLookasideList(pgSendMsgLookasideList))) + { + ERR("AllocateUserMessage(): Not enough memory to allocate a message"); + return NULL; + } + RtlZeroMemory(Message, sizeof(USER_SENT_MESSAGE)); + + if (KEvent) + { + Message->pkCompletionEvent = &Message->CompletionEvent;; + + KeInitializeEvent(Message->pkCompletionEvent, NotificationEvent, FALSE); + } + SendMsgCount++; + //ERR("AUM pti %p msg %p\n",PsGetCurrentThreadWin32Thread(),Message); + return Message; +} + +VOID FASTCALL +FreeUserMessage(PUSER_SENT_MESSAGE Message) +{ + Message->pkCompletionEvent = NULL; + + /* Remove it from the list */ + RemoveEntryList(&Message->ListEntry); + + ExFreeToPagedLookasideList(pgMessageLookasideList, Message); + SendMsgCount--; +} + +VOID APIENTRY +MsqRemoveWindowMessagesFromQueue(PWND Window) +{ + PTHREADINFO pti; + PUSER_SENT_MESSAGE SentMessage; + PUSER_MESSAGE PostedMessage; + PLIST_ENTRY CurrentEntry, ListHead; + + ASSERT(Window); + + pti = Window->head.pti; + + /* remove the posted messages for this window */ + CurrentEntry = pti->PostedMessagesListHead.Flink; + ListHead = &pti->PostedMessagesListHead; + while (CurrentEntry != ListHead) + { + PostedMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry); + + if (PostedMessage->Msg.hwnd == Window->head.h) + { + if (PostedMessage->Msg.message == WM_QUIT && pti->QuitPosted == 0) + { + pti->QuitPosted = 1; + pti->exitCode = PostedMessage->Msg.wParam; + } + RemoveEntryList(&PostedMessage->ListEntry); + ClearMsgBitsMask(pti, PostedMessage->QS_Flags); + MsqDestroyMessage(PostedMessage); + CurrentEntry = pti->PostedMessagesListHead.Flink; + } + else + { + CurrentEntry = CurrentEntry->Flink; + } + } + + /* remove the sent messages for this window */ + CurrentEntry = pti->SentMessagesListHead.Flink; + ListHead = &pti->SentMessagesListHead; + while (CurrentEntry != ListHead) + { + SentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, ListEntry); + + if(SentMessage->Msg.hwnd == Window->head.h) + { + TRACE("Remove Window Messages From Sent Queue\n"); + + ClearMsgBitsMask(pti, SentMessage->QS_Flags); + + /* wake the sender's thread */ + if (SentMessage->pkCompletionEvent != NULL) + { + KeSetEvent(SentMessage->pkCompletionEvent, IO_NO_INCREMENT, FALSE); + } + + if (SentMessage->HasPackedLParam) + { + if (SentMessage->Msg.lParam) + ExFreePool((PVOID)SentMessage->Msg.lParam); + } + + /* free the message */ + FreeUserMessage(SentMessage); + + CurrentEntry = pti->SentMessagesListHead.Flink; + } + else + { + CurrentEntry = CurrentEntry->Flink; + } + } +} + BOOLEAN FASTCALL co_MsqDispatchOneSentMessage( _In_ PTHREADINFO pti) @@ -762,6 +887,9 @@ /* remove it from the list of pending messages */ Entry = RemoveHeadList(&pti->SentMessagesListHead); Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry); + + // Signal this message is being processed. + Message->flags |= SMF_RECEIVERBUSY|SMF_RECEIVEDMESSAGE;
SaveMsg = pti->pusmCurrent; pti->pusmCurrent = Message; @@ -773,15 +901,14 @@ pti->pcti->CTI_flags |= CTI_INSENDMESSAGE; // Let the user know... }
- /* insert it to the list of messages that are currently dispatched by this - message queue */ - InsertTailList(&pti->LocalDispatchingMessagesHead, &Message->ListEntry); + /* Now insert it to the global list of messages that can be removed Justin Case there's Trouble */ + InsertTailList(&usmList, &Message->ListEntry);
ClearMsgBitsMask(pti, Message->QS_Flags);
if (Message->HookMessage == MSQ_ISHOOK) { // Direct Hook Call processor - Result = co_CallHook( Message->Msg.message, // HookId + Result = co_CallHook( Message->Msg.message, // HookId (INT)(INT_PTR)Message->Msg.hwnd, // Code Message->Msg.wParam, Message->Msg.lParam); @@ -810,7 +937,9 @@ /* The message has not been processed yet, reinsert it. */ RemoveEntryList(&Message->ListEntry); InsertTailList(&Message->ptiCallBackSender->SentMessagesListHead, &Message->ListEntry); - TRACE("Callback Message not processed yet. Requeuing the message\n"); + // List is occupied need to set the bit. + MsqWakeQueue(Message->ptiCallBackSender, QS_SENDMESSAGE, TRUE); + ERR("Callback Message not processed yet. Requeuing the message\n"); //// <---- Need to see if this happens. Ret = FALSE; goto Exit; } @@ -823,10 +952,6 @@ Message->Msg.lParam); }
- /* remove the message from the local dispatching list, because it doesn't need - to be cleaned up on thread termination anymore */ - RemoveEntryList(&Message->ListEntry); - /* If the message is a callback, insert it in the callback senders MessageQueue */ if (Message->CompletionCallback) { @@ -836,6 +961,7 @@ Message->QS_Flags |= QS_SMRESULT;
/* insert it in the callers message queue */ + RemoveEntryList(&Message->ListEntry); InsertTailList(&Message->ptiCallBackSender->SentMessagesListHead, &Message->ListEntry); MsqWakeQueue(Message->ptiCallBackSender, QS_SENDMESSAGE, TRUE); } @@ -843,29 +969,14 @@ goto Exit; }
- /* remove the message from the dispatching list if needed, so lock the sender's message queue */ - if (Message->ptiSender && !(Message->ptiSender->TIF_flags & TIF_INCLEANUP)) - { - if (!IsListEmpty(&Message->DispatchingListEntry)) - { - /* only remove it from the dispatching list if not already removed by a timeout */ - RemoveEntryList(&Message->DispatchingListEntry); - InitializeListHead(&Message->DispatchingListEntry); - } - } - - /* still keep the sender's message queue locked, so the sender can't exit the - MsqSendMessage() function (if timed out) */ + // Retrieve the result from callback. if (Message->QS_Flags & QS_SMRESULT) { Result = Message->lResult; }
/* Let the sender know the result. */ - if (Message->Result != NULL) - { - *Message->Result = Result; - } + Message->lResult = Result;
if (Message->HasPackedLParam) { @@ -873,14 +984,22 @@ ExFreePool((PVOID)Message->Msg.lParam); }
+ // Clear busy signal. + Message->flags &= ~SMF_RECEIVERBUSY; + /* Notify the sender. */ - if (Message->CompletionEvent != NULL) - { - KeSetEvent(Message->CompletionEvent, IO_NO_INCREMENT, FALSE); + if (Message->pkCompletionEvent != NULL) + { + KeSetEvent(Message->pkCompletionEvent, IO_NO_INCREMENT, FALSE); }
/* free the message */ - ExFreePoolWithTag(Message, TAG_USRMSG); + if (Message->flags & SMF_RECEIVERFREE) + { + TRACE("Receiver Freeing Message %p\n",Message); + FreeUserMessage(Message); + } + Ret = TRUE; Exit: /* do not hangup on the user if this is reentering */ @@ -888,89 +1007,6 @@ pti->pusmCurrent = SaveMsg;
return Ret; -} - -VOID APIENTRY -MsqRemoveWindowMessagesFromQueue(PWND Window) -{ - PTHREADINFO pti; - PUSER_SENT_MESSAGE SentMessage; - PUSER_MESSAGE PostedMessage; - PLIST_ENTRY CurrentEntry, ListHead; - - ASSERT(Window); - - pti = Window->head.pti; - - /* remove the posted messages for this window */ - CurrentEntry = pti->PostedMessagesListHead.Flink; - ListHead = &pti->PostedMessagesListHead; - while (CurrentEntry != ListHead) - { - PostedMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, - ListEntry); - if (PostedMessage->Msg.hwnd == Window->head.h) - { - if (PostedMessage->Msg.message == WM_QUIT && pti->QuitPosted == 0) - { - pti->QuitPosted = 1; - pti->exitCode = PostedMessage->Msg.wParam; - } - RemoveEntryList(&PostedMessage->ListEntry); - ClearMsgBitsMask(pti, PostedMessage->QS_Flags); - MsqDestroyMessage(PostedMessage); - CurrentEntry = pti->PostedMessagesListHead.Flink; - } - else - { - CurrentEntry = CurrentEntry->Flink; - } - } - - /* remove the sent messages for this window */ - CurrentEntry = pti->SentMessagesListHead.Flink; - ListHead = &pti->SentMessagesListHead; - while (CurrentEntry != ListHead) - { - SentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, ListEntry); - - if(SentMessage->Msg.hwnd == Window->head.h) - { - TRACE("Notify the sender and remove a message from the queue that had not been dispatched\n"); - - RemoveEntryList(&SentMessage->ListEntry); - ClearMsgBitsMask(pti, SentMessage->QS_Flags); - - /* Only if the message has a sender was the queue referenced */ - if ((SentMessage->ptiSender) && - (!IsListEmpty(&SentMessage->DispatchingListEntry))) - { - RemoveEntryList(&SentMessage->DispatchingListEntry); - InitializeListHead(&SentMessage->DispatchingListEntry); - } - - /* wake the sender's thread */ - if (SentMessage->CompletionEvent != NULL) - { - KeSetEvent(SentMessage->CompletionEvent, IO_NO_INCREMENT, FALSE); - } - - if (SentMessage->HasPackedLParam) - { - if (SentMessage->Msg.lParam) - ExFreePool((PVOID)SentMessage->Msg.lParam); - } - - /* free the message */ - ExFreePoolWithTag(SentMessage, TAG_USRMSG); - - CurrentEntry = pti->SentMessagesListHead.Flink; - } - else - { - CurrentEntry = CurrentEntry->Flink; - } - } }
BOOL FASTCALL @@ -988,9 +1024,9 @@ PTHREADINFO ptiSender; PUSER_SENT_MESSAGE Message;
- if(!(Message = ExAllocatePoolWithTag(NonPagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG))) - { - ERR("MsqSendMessage(): Not enough memory to allocate a message"); + if(!(Message = AllocateUserMessage(FALSE))) + { + ERR("MsqSendMessageAsync(): Not enough memory to allocate a message"); return FALSE; }
@@ -1000,18 +1036,15 @@ Message->Msg.message = Msg; Message->Msg.wParam = wParam; Message->Msg.lParam = lParam; - Message->CompletionEvent = NULL; - Message->Result = 0; - Message->lResult = 0; + Message->pkCompletionEvent = NULL; // No event needed. Message->ptiReceiver = ptiReceiver; - Message->ptiSender = NULL; Message->ptiCallBackSender = ptiSender; - InitializeListHead(&Message->DispatchingListEntry); Message->CompletionCallback = CompletionCallback; Message->CompletionCallbackContext = CompletionCallbackContext; Message->HookMessage = HookMessage; Message->HasPackedLParam = HasPackedLParam; Message->QS_Flags = QS_SENDMESSAGE; + Message->flags = SMF_RECEIVERFREE;
InsertTailList(&ptiReceiver->SentMessagesListHead, &Message->ListEntry); MsqWakeQueue(ptiReceiver, QS_SENDMESSAGE, TRUE); @@ -1031,12 +1064,12 @@ ULONG_PTR *uResult) { PTHREADINFO pti; - PUSER_SENT_MESSAGE Message; - KEVENT CompletionEvent; + PUSER_SENT_MESSAGE SaveMsg, Message; NTSTATUS WaitStatus; LARGE_INTEGER Timeout; PLIST_ENTRY Entry; PWND pWnd; + BOOLEAN SwapStateEnabled; LRESULT Result = 0; //// Result could be trashed. ////
pti = PsGetCurrentThreadWin32Thread(); @@ -1105,57 +1138,57 @@ } }
- if(!(Message = ExAllocatePoolWithTag(PagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG))) + if(!(Message = AllocateUserMessage(TRUE))) { ERR("MsqSendMessage(): Not enough memory to allocate a message\n"); + if (uResult) *uResult = -1; return STATUS_INSUFFICIENT_RESOURCES; } - - KeInitializeEvent(&CompletionEvent, NotificationEvent, FALSE);
Timeout.QuadPart = Int32x32To64(-10000,uTimeout); // Pass SMTO test with a TO of 0x80000000. TRACE("Timeout val %lld\n",Timeout.QuadPart) - - /* FIXME: Increase reference counter of sender's message queue here */
Message->Msg.hwnd = Wnd; Message->Msg.message = Msg; Message->Msg.wParam = wParam; Message->Msg.lParam = lParam; - Message->CompletionEvent = &CompletionEvent; - Message->Result = &Result; - Message->lResult = 0; - Message->QS_Flags = 0; Message->ptiReceiver = ptirec; Message->ptiSender = pti; - Message->ptiCallBackSender = NULL; - Message->CompletionCallback = NULL; - Message->CompletionCallbackContext = 0; Message->HookMessage = HookMessage; - Message->HasPackedLParam = FALSE; - - /* Add it to the list of pending messages */ - InsertTailList(&pti->DispatchingMessagesHead, &Message->DispatchingListEntry); + Message->QS_Flags = QS_SENDMESSAGE; + + SaveMsg = pti->pusmSent; + pti->pusmSent = Message;
/* Queue it in the destination's message queue */ InsertTailList(&ptirec->SentMessagesListHead, &Message->ListEntry);
- Message->QS_Flags = QS_SENDMESSAGE; MsqWakeQueue(ptirec, QS_SENDMESSAGE, TRUE);
- /* We can't access the Message anymore since it could have already been deleted! */ + // First time in, turn off swapping of the stack. + if (pti->cEnterCount == 0) + { + SwapStateEnabled = KeSetKernelStackSwapEnable(FALSE); + } + pti->cEnterCount++;
if (Block) { PVOID WaitObjects[2];
- WaitObjects[0] = &CompletionEvent; // Wait 0 - WaitObjects[1] = ptirec->pEThread; // Wait 1 + WaitObjects[0] = Message->pkCompletionEvent; // Wait 0 + WaitObjects[1] = ptirec->pEThread; // Wait 1
UserLeaveCo();
- WaitStatus = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, UserRequest, - UserMode, FALSE, (uTimeout ? &Timeout : NULL), NULL); + WaitStatus = KeWaitForMultipleObjects( 2, + WaitObjects, + WaitAny, + UserRequest, + UserMode, + FALSE, + (uTimeout ? &Timeout : NULL), + NULL );
UserEnterCo();
@@ -1168,39 +1201,24 @@ { if (CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry) == Message) { - /* We can access Message here, it's secure because the message queue is locked - and the message is still hasn't been dispatched */ - Message->CompletionEvent = NULL; - Message->Result = NULL; + Message->pkCompletionEvent = NULL; RemoveEntryList(&Message->ListEntry); - RemoveEntryList(&Message->DispatchingListEntry); ClearMsgBitsMask(ptirec, Message->QS_Flags); - ExFreePoolWithTag(Message, TAG_USRMSG); + InsertTailList(&usmList, &Message->ListEntry); break; } Entry = Entry->Flink; }
- TRACE("MsqSendMessage (blocked) timed out 1 Status %lx\n", WaitStatus); + ERR("MsqSendMessage (blocked) timed out 1 Status %lx\n", WaitStatus); } // Receiving thread passed on and left us hanging with issues still pending. else if (WaitStatus == STATUS_WAIT_1) { ERR("Bk Receiving Thread woken up dead!\n"); - Entry = pti->DispatchingMessagesHead.Flink; - while (Entry != &pti->DispatchingMessagesHead) - { - if (CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, DispatchingListEntry) == Message) - { - Message->CompletionEvent = NULL; - Message->Result = NULL; - RemoveEntryList(&Message->DispatchingListEntry); - InitializeListHead(&Message->DispatchingListEntry); - break; - } - Entry = Entry->Flink; - } + Message->flags |= SMF_RECEIVERDIED; } + while (co_MsqDispatchOneSentMessage(pti)) ; } @@ -1208,16 +1226,22 @@ { PVOID WaitObjects[3];
- WaitObjects[0] = &CompletionEvent; // Wait 0 - WaitObjects[1] = pti->pEventQueueServer; // Wait 1 - WaitObjects[2] = ptirec->pEThread; // Wait 2 + WaitObjects[0] = Message->pkCompletionEvent; // Wait 0 + WaitObjects[1] = pti->pEventQueueServer; // Wait 1 + WaitObjects[2] = ptirec->pEThread; // Wait 2
do { UserLeaveCo();
- WaitStatus = KeWaitForMultipleObjects(3, WaitObjects, WaitAny, UserRequest, - UserMode, FALSE, (uTimeout ? &Timeout : NULL), NULL); + WaitStatus = KeWaitForMultipleObjects( 3, + WaitObjects, + WaitAny, + UserRequest, + UserMode, + FALSE, + (uTimeout ? &Timeout : NULL), + NULL);
UserEnterCo();
@@ -1230,41 +1254,23 @@ { if (CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry) == Message) { - /* We can access Message here, it's secure because the message queue is locked - and the message is still hasn't been dispatched */ - Message->CompletionEvent = NULL; - Message->Result = NULL; + Message->pkCompletionEvent = NULL; RemoveEntryList(&Message->ListEntry); - RemoveEntryList(&Message->DispatchingListEntry); - InitializeListHead(&Message->DispatchingListEntry); ClearMsgBitsMask(ptirec, Message->QS_Flags); - ExFreePoolWithTag(Message, TAG_USRMSG); + InsertTailList(&usmList, &Message->ListEntry); break; } Entry = Entry->Flink; }
- TRACE("MsqSendMessage timed out 2 Status %lx\n", WaitStatus); - + ERR("MsqSendMessage timed out 2 Status %lx\n", WaitStatus); break; } // Receiving thread passed on and left us hanging with issues still pending. else if (WaitStatus == STATUS_WAIT_2) { ERR("NB Receiving Thread woken up dead!\n"); - Entry = pti->DispatchingMessagesHead.Flink; - while (Entry != &pti->DispatchingMessagesHead) - { - if (CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, DispatchingListEntry) == Message) - { - Message->CompletionEvent = NULL; - Message->Result = NULL; - RemoveEntryList(&Message->DispatchingListEntry); - InitializeListHead(&Message->DispatchingListEntry); - break; - } - Entry = Entry->Flink; - } + Message->flags |= SMF_RECEIVERDIED; break; }
@@ -1275,19 +1281,52 @@ } while (WaitStatus == STATUS_WAIT_1); }
+ // Count is nil, restore swapping of the stack. + if (--pti->cEnterCount == 0 ) + { + KeSetKernelStackSwapEnable(SwapStateEnabled); + } + + // Handle User APC if (WaitStatus == STATUS_USER_APC) { // The current thread is dying! TRACE("User APC\n"); + + // The Message will be on the Trouble list until Thread cleanup. + Message->flags |= SMF_SENDERDIED; + co_IntDeliverUserAPC(); ERR("User APC Returned\n"); // Should not see this message. }
+ // Force this thread to wake up for the next go around. + KeSetEvent(pti->pEventQueueServer, IO_NO_INCREMENT, FALSE); + + Result = Message->lResult; + + // Determine whether this message is being processed or not. + if ((Message->flags & (SMF_RECEIVERBUSY|SMF_RECEIVEDMESSAGE)) != SMF_RECEIVEDMESSAGE) + { + Message->flags |= SMF_RECEIVERFREE; + } + + if (!(Message->flags & SMF_RECEIVERFREE)) + { + TRACE("Sender Freeing Message %p ptirec %p bit %d list empty %d\n",Message,ptirec,!!(ptirec->pcti->fsChangeBits & QS_SENDMESSAGE),IsListEmpty(&ptirec->SentMessagesListHead)); + // Make it to this point, the message was received. + FreeUserMessage(Message); + } + + pti->pusmSent = SaveMsg; + + TRACE("MSM Allocation Count %d Status %lx Result %d\n",SendMsgCount,WaitStatus,Result); + if (WaitStatus != STATUS_TIMEOUT) { if (uResult) { - *uResult = (STATUS_WAIT_0 == WaitStatus ? Result : -1); + *uResult = (STATUS_WAIT_0 == WaitStatus ? Result : 0); } }
@@ -2104,6 +2143,23 @@ PUSER_MESSAGE CurrentMessage; PUSER_SENT_MESSAGE CurrentSentMessage;
+ TRACE("MsqCleanupThreadMsgs %p\n",pti); + + // Clear it all out. + if (pti->pcti) + { + pti->pcti->fsWakeBits = 0; + pti->pcti->fsChangeBits = 0; + } + + pti->nCntsQBits[QSRosKey] = 0; + pti->nCntsQBits[QSRosMouseMove] = 0; + pti->nCntsQBits[QSRosMouseButton] = 0; + pti->nCntsQBits[QSRosPostMessage] = 0; + pti->nCntsQBits[QSRosSendMessage] = 0; + pti->nCntsQBits[QSRosHotKey] = 0; + pti->nCntsQBits[QSRosEvent] = 0; + /* cleanup posted messages */ while (!IsListEmpty(&pti->PostedMessagesListHead)) { @@ -2122,22 +2178,15 @@ /* remove the messages that have not yet been dispatched */ while (!IsListEmpty(&pti->SentMessagesListHead)) { - CurrentEntry = RemoveHeadList(&pti->SentMessagesListHead); + CurrentEntry = pti->SentMessagesListHead.Flink; CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, ListEntry);
- TRACE("Notify the sender and remove a message from the queue that had not been dispatched\n"); - /* Only if the message has a sender was the message in the DispatchingList */ - if ((CurrentSentMessage->ptiSender) && - (!IsListEmpty(&CurrentSentMessage->DispatchingListEntry))) + ERR("Thread Cleanup Sent Messages\n"); + + /* wake the sender's thread */ + if (CurrentSentMessage->pkCompletionEvent != NULL) { - RemoveEntryList(&CurrentSentMessage->DispatchingListEntry); - InitializeListHead(&CurrentSentMessage->DispatchingListEntry); - } - - /* wake the sender's thread */ - if (CurrentSentMessage->CompletionEvent != NULL) - { - KeSetEvent(CurrentSentMessage->CompletionEvent, IO_NO_INCREMENT, FALSE); + KeSetEvent(CurrentSentMessage->pkCompletionEvent, IO_NO_INCREMENT, FALSE); }
if (CurrentSentMessage->HasPackedLParam) @@ -2147,71 +2196,49 @@ }
/* free the message */ - ExFreePool(CurrentSentMessage); - } - - /* notify senders of dispatching messages. This needs to be cleaned up if e.g. - ExitThread() was called in a SendMessage() umode callback */ - while (!IsListEmpty(&pti->LocalDispatchingMessagesHead)) - { - CurrentEntry = RemoveHeadList(&pti->LocalDispatchingMessagesHead); - CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, ListEntry); - - /* remove the message from the dispatching list */ - if (!IsListEmpty(&CurrentSentMessage->DispatchingListEntry)) + FreeUserMessage(CurrentSentMessage); + } + + // Process Trouble Message List + if (!IsListEmpty(&usmList)) + { + CurrentEntry = usmList.Flink; + while (CurrentEntry != &usmList) { - RemoveEntryList(&CurrentSentMessage->DispatchingListEntry); - InitializeListHead(&CurrentSentMessage->DispatchingListEntry); - } - - TRACE("Notify the sender, the thread has been terminated while dispatching a message!\n"); - - /* wake the sender's thread */ - if (CurrentSentMessage->CompletionEvent != NULL) - { - KeSetEvent(CurrentSentMessage->CompletionEvent, IO_NO_INCREMENT, FALSE); - } - - if (CurrentSentMessage->HasPackedLParam) - { - if (CurrentSentMessage->Msg.lParam) + CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, ListEntry); + CurrentEntry = CurrentEntry->Flink; + + TRACE("Found troubled messages on the list\n"); + + if ( pti == CurrentSentMessage->ptiReceiver ) { - _PRAGMA_WARNING_SUPPRESS(__WARNING_USING_UNINIT_VAR); - ExFreePool((PVOID)CurrentSentMessage->Msg.lParam); + if (CurrentSentMessage->HasPackedLParam) + { + if (CurrentSentMessage->Msg.lParam) + ExFreePool((PVOID)CurrentSentMessage->Msg.lParam); + } + + /* free the message */ + FreeUserMessage(CurrentSentMessage); + } + else if ( pti == CurrentSentMessage->ptiSender || + pti == CurrentSentMessage->ptiCallBackSender ) + { + if (!(CurrentSentMessage->flags & SMF_RECEIVERFREE)) + { + + if (CurrentSentMessage->HasPackedLParam) + { + if (CurrentSentMessage->Msg.lParam) + ExFreePool((PVOID)CurrentSentMessage->Msg.lParam); + } + + /* free the message */ + FreeUserMessage(CurrentSentMessage); + } } } - - /* free the message */ - ExFreePool(CurrentSentMessage); - } - - /* tell other threads not to bother returning any info to us */ - while (! IsListEmpty(&pti->DispatchingMessagesHead)) - { - CurrentEntry = RemoveHeadList(&pti->DispatchingMessagesHead); - CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, DispatchingListEntry); - InitializeListHead(&CurrentSentMessage->DispatchingListEntry); - CurrentSentMessage->CompletionEvent = NULL; - CurrentSentMessage->Result = NULL; - - /* do NOT dereference our message queue as it might get attempted to be - locked later */ - } - - // Clear it all out. - if (pti->pcti) - { - pti->pcti->fsWakeBits = 0; - pti->pcti->fsChangeBits = 0; - } - - pti->nCntsQBits[QSRosKey] = 0; - pti->nCntsQBits[QSRosMouseMove] = 0; - pti->nCntsQBits[QSRosMouseButton] = 0; - pti->nCntsQBits[QSRosPostMessage] = 0; - pti->nCntsQBits[QSRosSendMessage] = 0; - pti->nCntsQBits[QSRosHotKey] = 0; - pti->nCntsQBits[QSRosEvent] = 0; + } }
VOID FASTCALL @@ -2364,7 +2391,7 @@
if (Message->QS_Flags & QS_SMRESULT) return FALSE;
- // SendMessageXxx || Callback msg and not a notify msg + // SendMessageXxx || Callback msg and not a notify msg if (Message->ptiSender || Message->CompletionCallback) { Message->lResult = lResult;
Modified: trunk/reactos/win32ss/user/ntuser/msgqueue.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/msgqueu... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/msgqueue.h [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/msgqueue.h [iso-8859-1] Tue Nov 3 15:18:51 2015 @@ -22,19 +22,24 @@ LIST_ENTRY ListEntry; MSG Msg; DWORD QS_Flags; // Original QS bits used to create this message. - PKEVENT CompletionEvent; - LRESULT* Result; + PKEVENT pkCompletionEvent; LRESULT lResult; + DWORD flags; PTHREADINFO ptiSender; PTHREADINFO ptiReceiver; SENDASYNCPROC CompletionCallback; PTHREADINFO ptiCallBackSender; ULONG_PTR CompletionCallbackContext; - /* entry in the dispatching list of the sender's message queue */ - LIST_ENTRY DispatchingListEntry; INT HookMessage; BOOL HasPackedLParam; + KEVENT CompletionEvent; } USER_SENT_MESSAGE, *PUSER_SENT_MESSAGE; + +#define SMF_RECEIVERDIED 0x00000002 +#define SMF_SENDERDIED 0x00000004 +#define SMF_RECEIVERFREE 0x00000008 +#define SMF_RECEIVEDMESSAGE 0x00000010 +#define SMF_RECEIVERBUSY 0x00004000
typedef struct _USER_MESSAGE_QUEUE { @@ -116,6 +121,8 @@ };
#define POSTEVENT_NWE 14 + +extern LIST_ENTRY usmList;
BOOL FASTCALL MsqIsHung(PTHREADINFO pti); VOID CALLBACK HungAppSysTimerProc(HWND,UINT,UINT_PTR,DWORD); @@ -252,6 +259,9 @@ BOOL FASTCALL IntCallMsgFilter(LPMSG,INT); WPARAM FASTCALL MsqGetDownKeyState(PUSER_MESSAGE_QUEUE); BOOL FASTCALL IsThreadSuspended(PTHREADINFO); +PUSER_SENT_MESSAGE FASTCALL AllocateUserMessage(BOOL); +VOID FASTCALL FreeUserMessage(PUSER_SENT_MESSAGE); +
int UserShowCursor(BOOL bShow); PCURICON_OBJECT
Modified: trunk/reactos/win32ss/user/ntuser/win32.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/win32.h... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/win32.h [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/win32.h [iso-8859-1] Tue Nov 3 15:18:51 2015 @@ -93,8 +93,7 @@ struct _CLIENTINFO * pClientInfo; FLONG TIF_flags; PUNICODE_STRING pstrAppName; - /* Messages that are currently dispatched to other threads */ - LIST_ENTRY DispatchingMessagesHead; // psmsSent + struct _USER_SENT_MESSAGE *pusmSent; struct _USER_SENT_MESSAGE *pusmCurrent; /* Queue of messages sent to the queue. */ LIST_ENTRY SentMessagesListHead; // psmsReceiveList @@ -127,6 +126,7 @@ INT iCursorLevel; POINT ptLast;
+ INT cEnterCount; /* Queue of messages posted to the queue. */ LIST_ENTRY PostedMessagesListHead; // mlPost WORD fsChangeBitsRemoved; @@ -146,8 +146,6 @@ // Accounting of queue bit sets, the rest are flags. QS_TIMER QS_PAINT counts are handled in thread information. DWORD nCntsQBits[QSIDCOUNTS]; // QS_KEY QS_MOUSEMOVE QS_MOUSEBUTTON QS_POSTMESSAGE QS_SENDMESSAGE QS_HOTKEY
- /* Messages that are currently dispatched by this message queue, required for cleanup */ - LIST_ENTRY LocalDispatchingMessagesHead; LIST_ENTRY WindowListHead; LIST_ENTRY W32CallbackListHead; SINGLE_LIST_ENTRY ReferencesList;