mirror of
https://github.com/reactos/reactos.git
synced 2024-07-01 02:10:07 +00:00
[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. svn path=/trunk/; revision=69793
This commit is contained in:
parent
8584094adc
commit
598aff78e9
|
@ -51,13 +51,19 @@ IntCbFreeMemory(PVOID Data)
|
||||||
PINT_CALLBACK_HEADER Mem;
|
PINT_CALLBACK_HEADER Mem;
|
||||||
PTHREADINFO W32Thread;
|
PTHREADINFO W32Thread;
|
||||||
|
|
||||||
|
W32Thread = PsGetCurrentThreadWin32Thread();
|
||||||
|
ASSERT(W32Thread);
|
||||||
|
|
||||||
|
if (W32Thread->TIF_flags & TIF_INCLEANUP)
|
||||||
|
{
|
||||||
|
ERR("CbFM Thread is already in cleanup\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT(Data);
|
ASSERT(Data);
|
||||||
|
|
||||||
Mem = ((PINT_CALLBACK_HEADER)Data - 1);
|
Mem = ((PINT_CALLBACK_HEADER)Data - 1);
|
||||||
|
|
||||||
W32Thread = PsGetCurrentThreadWin32Thread();
|
|
||||||
ASSERT(W32Thread);
|
|
||||||
|
|
||||||
/* Remove the memory block from the thread's callback list */
|
/* Remove the memory block from the thread's callback list */
|
||||||
RemoveEntryList(&Mem->ListEntry);
|
RemoveEntryList(&Mem->ListEntry);
|
||||||
|
|
||||||
|
@ -340,8 +346,9 @@ co_IntCallWindowProc(WNDPROC Proc,
|
||||||
&ResultLength);
|
&ResultLength);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
ERR("Error Callback to User space Status %lx\n",Status);
|
||||||
UserEnterCo();
|
UserEnterCo();
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
|
|
|
@ -340,7 +340,13 @@ FindRemoveAsyncMsg(PWND Wnd, WPARAM wParam)
|
||||||
WARN("ASYNC SAW: Found one in the Sent Msg Queue! %p Activate/Deactivate %d\n", Message->Msg.hwnd, !!wParam);
|
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.
|
RemoveEntryList(&Message->ListEntry); // Purge the entry.
|
||||||
ClearMsgBitsMask(pti, Message->QS_Flags);
|
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 @@ co_UserSetCapture(HWND hWnd)
|
||||||
{
|
{
|
||||||
if (Window->head.pti->MessageQueue != ThreadQueue)
|
if (Window->head.pti->MessageQueue != ThreadQueue)
|
||||||
{
|
{
|
||||||
ERR("Window Thread dos not match Current!\n");
|
ERR("Window Thread does not match Current!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -488,8 +488,6 @@ InitThreadCallback(PETHREAD Thread)
|
||||||
InitializeListHead(&ptiCurrent->W32CallbackListHead);
|
InitializeListHead(&ptiCurrent->W32CallbackListHead);
|
||||||
InitializeListHead(&ptiCurrent->PostedMessagesListHead);
|
InitializeListHead(&ptiCurrent->PostedMessagesListHead);
|
||||||
InitializeListHead(&ptiCurrent->SentMessagesListHead);
|
InitializeListHead(&ptiCurrent->SentMessagesListHead);
|
||||||
InitializeListHead(&ptiCurrent->DispatchingMessagesHead);
|
|
||||||
InitializeListHead(&ptiCurrent->LocalDispatchingMessagesHead);
|
|
||||||
InitializeListHead(&ptiCurrent->PtiLink);
|
InitializeListHead(&ptiCurrent->PtiLink);
|
||||||
for (i = 0; i < NB_HOOKS; i++)
|
for (i = 0; i < NB_HOOKS; i++)
|
||||||
{
|
{
|
||||||
|
@ -778,6 +776,12 @@ ExitThreadCallback(PETHREAD Thread)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ptiCurrent->cEnterCount)
|
||||||
|
{
|
||||||
|
KeSetKernelStackSwapEnable(TRUE);
|
||||||
|
ptiCurrent->cEnterCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find the THREADINFO in the PROCESSINFO's list */
|
/* Find the THREADINFO in the PROCESSINFO's list */
|
||||||
ppti = &ppiCurrent->ptiList;
|
ppti = &ppiCurrent->ptiList;
|
||||||
while (*ppti != NULL && *ppti != ptiCurrent)
|
while (*ppti != NULL && *ppti != ptiCurrent)
|
||||||
|
|
|
@ -1278,7 +1278,7 @@ co_IntSendMessage( HWND hWnd,
|
||||||
LPARAM lParam )
|
LPARAM lParam )
|
||||||
{
|
{
|
||||||
ULONG_PTR Result = 0;
|
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;
|
return (LRESULT)Result;
|
||||||
}
|
}
|
||||||
|
@ -1399,7 +1399,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
|
||||||
wParam,
|
wParam,
|
||||||
lParamPacked,
|
lParamPacked,
|
||||||
lParamBufferSize );
|
lParamBufferSize );
|
||||||
if(uResult)
|
if (uResult)
|
||||||
{
|
{
|
||||||
*uResult = Result;
|
*uResult = Result;
|
||||||
}
|
}
|
||||||
|
@ -1697,7 +1697,7 @@ co_IntSendMessageWithCallBack( HWND hWnd,
|
||||||
RETURN(TRUE);
|
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");
|
ERR("MsqSendMessage(): Not enough memory to allocate a message");
|
||||||
RETURN( FALSE);
|
RETURN( FALSE);
|
||||||
|
@ -1707,19 +1707,18 @@ co_IntSendMessageWithCallBack( HWND hWnd,
|
||||||
Message->Msg.message = Msg;
|
Message->Msg.message = Msg;
|
||||||
Message->Msg.wParam = wParam;
|
Message->Msg.wParam = wParam;
|
||||||
Message->Msg.lParam = lParamPacked;
|
Message->Msg.lParam = lParamPacked;
|
||||||
Message->CompletionEvent = NULL;
|
Message->pkCompletionEvent = NULL; // No event needed.
|
||||||
Message->Result = 0;
|
|
||||||
Message->lResult = 0;
|
Message->lResult = 0;
|
||||||
Message->QS_Flags = 0;
|
Message->QS_Flags = 0;
|
||||||
Message->ptiReceiver = ptiSendTo;
|
Message->ptiReceiver = ptiSendTo;
|
||||||
Message->ptiSender = NULL; // mjmartin, you are right! This is null.
|
Message->ptiSender = NULL; // mjmartin, you are right! This is null.
|
||||||
Message->ptiCallBackSender = Win32Thread;
|
Message->ptiCallBackSender = Win32Thread;
|
||||||
InitializeListHead(&Message->DispatchingListEntry);
|
|
||||||
Message->CompletionCallback = CompletionCallback;
|
Message->CompletionCallback = CompletionCallback;
|
||||||
Message->CompletionCallbackContext = CompletionCallbackContext;
|
Message->CompletionCallbackContext = CompletionCallbackContext;
|
||||||
Message->HookMessage = MSQ_NORMAL;
|
Message->HookMessage = MSQ_NORMAL;
|
||||||
Message->HasPackedLParam = (lParamBufferSize > 0);
|
Message->HasPackedLParam = (lParamBufferSize > 0);
|
||||||
Message->QS_Flags = QS_SENDMESSAGE;
|
Message->QS_Flags = QS_SENDMESSAGE;
|
||||||
|
Message->flags = SMF_RECEIVERFREE;
|
||||||
|
|
||||||
if (Msg & 0x80000000) // Higher priority event message!
|
if (Msg & 0x80000000) // Higher priority event message!
|
||||||
InsertHeadList(&ptiSendTo->SentMessagesListHead, &Message->ListEntry);
|
InsertHeadList(&ptiSendTo->SentMessagesListHead, &Message->ListEntry);
|
||||||
|
@ -2723,14 +2722,15 @@ NtUserMessageCall( HWND hWnd,
|
||||||
break;
|
break;
|
||||||
case FNID_SENDMESSAGE:
|
case FNID_SENDMESSAGE:
|
||||||
{
|
{
|
||||||
Ret = co_IntDoSendMessage(hWnd, Msg, wParam, lParam, 0);
|
lResult = co_IntDoSendMessage(hWnd, Msg, wParam, lParam, 0);
|
||||||
|
Ret = TRUE;
|
||||||
|
|
||||||
if (ResultInfo)
|
if (ResultInfo)
|
||||||
{
|
{
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
{
|
{
|
||||||
ProbeForWrite((PVOID)ResultInfo, sizeof(ULONG_PTR), 1);
|
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)
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,10 +14,12 @@ DBG_DEFAULT_CHANNEL(UserMsgQ);
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
static PPAGED_LOOKASIDE_LIST pgMessageLookasideList;
|
static PPAGED_LOOKASIDE_LIST pgMessageLookasideList;
|
||||||
|
static PPAGED_LOOKASIDE_LIST pgSendMsgLookasideList;
|
||||||
|
INT SendMsgCount = 0;
|
||||||
PUSER_MESSAGE_QUEUE gpqCursor;
|
PUSER_MESSAGE_QUEUE gpqCursor;
|
||||||
ULONG_PTR gdwMouseMoveExtraInfo = 0;
|
ULONG_PTR gdwMouseMoveExtraInfo = 0;
|
||||||
DWORD gdwMouseMoveTimeStamp = 0;
|
DWORD gdwMouseMoveTimeStamp = 0;
|
||||||
|
LIST_ENTRY usmList;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
@ -26,6 +28,7 @@ NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MsqInitializeImpl(VOID)
|
MsqInitializeImpl(VOID)
|
||||||
{
|
{
|
||||||
|
// Setup Post Messages
|
||||||
pgMessageLookasideList = ExAllocatePoolWithTag(NonPagedPool, sizeof(PAGED_LOOKASIDE_LIST), TAG_USRMSG);
|
pgMessageLookasideList = ExAllocatePoolWithTag(NonPagedPool, sizeof(PAGED_LOOKASIDE_LIST), TAG_USRMSG);
|
||||||
if (!pgMessageLookasideList)
|
if (!pgMessageLookasideList)
|
||||||
return STATUS_NO_MEMORY;
|
return STATUS_NO_MEMORY;
|
||||||
|
@ -36,6 +39,19 @@ MsqInitializeImpl(VOID)
|
||||||
sizeof(USER_MESSAGE),
|
sizeof(USER_MESSAGE),
|
||||||
TAG_USRMSG,
|
TAG_USRMSG,
|
||||||
256);
|
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);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -743,6 +759,115 @@ MsqDestroyMessage(PUSER_MESSAGE Message)
|
||||||
ExFreeToPagedLookasideList(pgMessageLookasideList, Message);
|
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
|
BOOLEAN FASTCALL
|
||||||
co_MsqDispatchOneSentMessage(
|
co_MsqDispatchOneSentMessage(
|
||||||
_In_ PTHREADINFO pti)
|
_In_ PTHREADINFO pti)
|
||||||
|
@ -763,6 +888,9 @@ co_MsqDispatchOneSentMessage(
|
||||||
Entry = RemoveHeadList(&pti->SentMessagesListHead);
|
Entry = RemoveHeadList(&pti->SentMessagesListHead);
|
||||||
Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
|
Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
|
||||||
|
|
||||||
|
// Signal this message is being processed.
|
||||||
|
Message->flags |= SMF_RECEIVERBUSY|SMF_RECEIVEDMESSAGE;
|
||||||
|
|
||||||
SaveMsg = pti->pusmCurrent;
|
SaveMsg = pti->pusmCurrent;
|
||||||
pti->pusmCurrent = Message;
|
pti->pusmCurrent = Message;
|
||||||
|
|
||||||
|
@ -773,15 +901,14 @@ co_MsqDispatchOneSentMessage(
|
||||||
pti->pcti->CTI_flags |= CTI_INSENDMESSAGE; // Let the user know...
|
pti->pcti->CTI_flags |= CTI_INSENDMESSAGE; // Let the user know...
|
||||||
}
|
}
|
||||||
|
|
||||||
/* insert it to the list of messages that are currently dispatched by this
|
/* Now insert it to the global list of messages that can be removed Justin Case there's Trouble */
|
||||||
message queue */
|
InsertTailList(&usmList, &Message->ListEntry);
|
||||||
InsertTailList(&pti->LocalDispatchingMessagesHead, &Message->ListEntry);
|
|
||||||
|
|
||||||
ClearMsgBitsMask(pti, Message->QS_Flags);
|
ClearMsgBitsMask(pti, Message->QS_Flags);
|
||||||
|
|
||||||
if (Message->HookMessage == MSQ_ISHOOK)
|
if (Message->HookMessage == MSQ_ISHOOK)
|
||||||
{ // Direct Hook Call processor
|
{ // 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
|
(INT)(INT_PTR)Message->Msg.hwnd, // Code
|
||||||
Message->Msg.wParam,
|
Message->Msg.wParam,
|
||||||
Message->Msg.lParam);
|
Message->Msg.lParam);
|
||||||
|
@ -810,7 +937,9 @@ co_MsqDispatchOneSentMessage(
|
||||||
/* The message has not been processed yet, reinsert it. */
|
/* The message has not been processed yet, reinsert it. */
|
||||||
RemoveEntryList(&Message->ListEntry);
|
RemoveEntryList(&Message->ListEntry);
|
||||||
InsertTailList(&Message->ptiCallBackSender->SentMessagesListHead, &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;
|
Ret = FALSE;
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
@ -823,10 +952,6 @@ co_MsqDispatchOneSentMessage(
|
||||||
Message->Msg.lParam);
|
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 the message is a callback, insert it in the callback senders MessageQueue */
|
||||||
if (Message->CompletionCallback)
|
if (Message->CompletionCallback)
|
||||||
{
|
{
|
||||||
|
@ -836,6 +961,7 @@ co_MsqDispatchOneSentMessage(
|
||||||
Message->QS_Flags |= QS_SMRESULT;
|
Message->QS_Flags |= QS_SMRESULT;
|
||||||
|
|
||||||
/* insert it in the callers message queue */
|
/* insert it in the callers message queue */
|
||||||
|
RemoveEntryList(&Message->ListEntry);
|
||||||
InsertTailList(&Message->ptiCallBackSender->SentMessagesListHead, &Message->ListEntry);
|
InsertTailList(&Message->ptiCallBackSender->SentMessagesListHead, &Message->ListEntry);
|
||||||
MsqWakeQueue(Message->ptiCallBackSender, QS_SENDMESSAGE, TRUE);
|
MsqWakeQueue(Message->ptiCallBackSender, QS_SENDMESSAGE, TRUE);
|
||||||
}
|
}
|
||||||
|
@ -843,29 +969,14 @@ co_MsqDispatchOneSentMessage(
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remove the message from the dispatching list if needed, so lock the sender's message queue */
|
// Retrieve the result from callback.
|
||||||
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) */
|
|
||||||
if (Message->QS_Flags & QS_SMRESULT)
|
if (Message->QS_Flags & QS_SMRESULT)
|
||||||
{
|
{
|
||||||
Result = Message->lResult;
|
Result = Message->lResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Let the sender know the result. */
|
/* Let the sender know the result. */
|
||||||
if (Message->Result != NULL)
|
Message->lResult = Result;
|
||||||
{
|
|
||||||
*Message->Result = Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Message->HasPackedLParam)
|
if (Message->HasPackedLParam)
|
||||||
{
|
{
|
||||||
|
@ -873,14 +984,22 @@ co_MsqDispatchOneSentMessage(
|
||||||
ExFreePool((PVOID)Message->Msg.lParam);
|
ExFreePool((PVOID)Message->Msg.lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear busy signal.
|
||||||
|
Message->flags &= ~SMF_RECEIVERBUSY;
|
||||||
|
|
||||||
/* Notify the sender. */
|
/* Notify the sender. */
|
||||||
if (Message->CompletionEvent != NULL)
|
if (Message->pkCompletionEvent != NULL)
|
||||||
{
|
{
|
||||||
KeSetEvent(Message->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
KeSetEvent(Message->pkCompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free the message */
|
/* free the message */
|
||||||
ExFreePoolWithTag(Message, TAG_USRMSG);
|
if (Message->flags & SMF_RECEIVERFREE)
|
||||||
|
{
|
||||||
|
TRACE("Receiver Freeing Message %p\n",Message);
|
||||||
|
FreeUserMessage(Message);
|
||||||
|
}
|
||||||
|
|
||||||
Ret = TRUE;
|
Ret = TRUE;
|
||||||
Exit:
|
Exit:
|
||||||
/* do not hangup on the user if this is reentering */
|
/* do not hangup on the user if this is reentering */
|
||||||
|
@ -890,89 +1009,6 @@ Exit:
|
||||||
return Ret;
|
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
|
BOOL FASTCALL
|
||||||
co_MsqSendMessageAsync(PTHREADINFO ptiReceiver,
|
co_MsqSendMessageAsync(PTHREADINFO ptiReceiver,
|
||||||
HWND hwnd,
|
HWND hwnd,
|
||||||
|
@ -988,9 +1024,9 @@ co_MsqSendMessageAsync(PTHREADINFO ptiReceiver,
|
||||||
PTHREADINFO ptiSender;
|
PTHREADINFO ptiSender;
|
||||||
PUSER_SENT_MESSAGE Message;
|
PUSER_SENT_MESSAGE Message;
|
||||||
|
|
||||||
if(!(Message = ExAllocatePoolWithTag(NonPagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG)))
|
if(!(Message = AllocateUserMessage(FALSE)))
|
||||||
{
|
{
|
||||||
ERR("MsqSendMessage(): Not enough memory to allocate a message");
|
ERR("MsqSendMessageAsync(): Not enough memory to allocate a message");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1000,18 +1036,15 @@ co_MsqSendMessageAsync(PTHREADINFO ptiReceiver,
|
||||||
Message->Msg.message = Msg;
|
Message->Msg.message = Msg;
|
||||||
Message->Msg.wParam = wParam;
|
Message->Msg.wParam = wParam;
|
||||||
Message->Msg.lParam = lParam;
|
Message->Msg.lParam = lParam;
|
||||||
Message->CompletionEvent = NULL;
|
Message->pkCompletionEvent = NULL; // No event needed.
|
||||||
Message->Result = 0;
|
|
||||||
Message->lResult = 0;
|
|
||||||
Message->ptiReceiver = ptiReceiver;
|
Message->ptiReceiver = ptiReceiver;
|
||||||
Message->ptiSender = NULL;
|
|
||||||
Message->ptiCallBackSender = ptiSender;
|
Message->ptiCallBackSender = ptiSender;
|
||||||
InitializeListHead(&Message->DispatchingListEntry);
|
|
||||||
Message->CompletionCallback = CompletionCallback;
|
Message->CompletionCallback = CompletionCallback;
|
||||||
Message->CompletionCallbackContext = CompletionCallbackContext;
|
Message->CompletionCallbackContext = CompletionCallbackContext;
|
||||||
Message->HookMessage = HookMessage;
|
Message->HookMessage = HookMessage;
|
||||||
Message->HasPackedLParam = HasPackedLParam;
|
Message->HasPackedLParam = HasPackedLParam;
|
||||||
Message->QS_Flags = QS_SENDMESSAGE;
|
Message->QS_Flags = QS_SENDMESSAGE;
|
||||||
|
Message->flags = SMF_RECEIVERFREE;
|
||||||
|
|
||||||
InsertTailList(&ptiReceiver->SentMessagesListHead, &Message->ListEntry);
|
InsertTailList(&ptiReceiver->SentMessagesListHead, &Message->ListEntry);
|
||||||
MsqWakeQueue(ptiReceiver, QS_SENDMESSAGE, TRUE);
|
MsqWakeQueue(ptiReceiver, QS_SENDMESSAGE, TRUE);
|
||||||
|
@ -1031,12 +1064,12 @@ co_MsqSendMessage(PTHREADINFO ptirec,
|
||||||
ULONG_PTR *uResult)
|
ULONG_PTR *uResult)
|
||||||
{
|
{
|
||||||
PTHREADINFO pti;
|
PTHREADINFO pti;
|
||||||
PUSER_SENT_MESSAGE Message;
|
PUSER_SENT_MESSAGE SaveMsg, Message;
|
||||||
KEVENT CompletionEvent;
|
|
||||||
NTSTATUS WaitStatus;
|
NTSTATUS WaitStatus;
|
||||||
LARGE_INTEGER Timeout;
|
LARGE_INTEGER Timeout;
|
||||||
PLIST_ENTRY Entry;
|
PLIST_ENTRY Entry;
|
||||||
PWND pWnd;
|
PWND pWnd;
|
||||||
|
BOOLEAN SwapStateEnabled;
|
||||||
LRESULT Result = 0; //// Result could be trashed. ////
|
LRESULT Result = 0; //// Result could be trashed. ////
|
||||||
|
|
||||||
pti = PsGetCurrentThreadWin32Thread();
|
pti = PsGetCurrentThreadWin32Thread();
|
||||||
|
@ -1105,57 +1138,57 @@ co_MsqSendMessage(PTHREADINFO ptirec,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(Message = ExAllocatePoolWithTag(PagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG)))
|
if(!(Message = AllocateUserMessage(TRUE)))
|
||||||
{
|
{
|
||||||
ERR("MsqSendMessage(): Not enough memory to allocate a message\n");
|
ERR("MsqSendMessage(): Not enough memory to allocate a message\n");
|
||||||
|
if (uResult) *uResult = -1;
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
KeInitializeEvent(&CompletionEvent, NotificationEvent, FALSE);
|
|
||||||
|
|
||||||
Timeout.QuadPart = Int32x32To64(-10000,uTimeout); // Pass SMTO test with a TO of 0x80000000.
|
Timeout.QuadPart = Int32x32To64(-10000,uTimeout); // Pass SMTO test with a TO of 0x80000000.
|
||||||
TRACE("Timeout val %lld\n",Timeout.QuadPart)
|
TRACE("Timeout val %lld\n",Timeout.QuadPart)
|
||||||
|
|
||||||
/* FIXME: Increase reference counter of sender's message queue here */
|
|
||||||
|
|
||||||
Message->Msg.hwnd = Wnd;
|
Message->Msg.hwnd = Wnd;
|
||||||
Message->Msg.message = Msg;
|
Message->Msg.message = Msg;
|
||||||
Message->Msg.wParam = wParam;
|
Message->Msg.wParam = wParam;
|
||||||
Message->Msg.lParam = lParam;
|
Message->Msg.lParam = lParam;
|
||||||
Message->CompletionEvent = &CompletionEvent;
|
|
||||||
Message->Result = &Result;
|
|
||||||
Message->lResult = 0;
|
|
||||||
Message->QS_Flags = 0;
|
|
||||||
Message->ptiReceiver = ptirec;
|
Message->ptiReceiver = ptirec;
|
||||||
Message->ptiSender = pti;
|
Message->ptiSender = pti;
|
||||||
Message->ptiCallBackSender = NULL;
|
|
||||||
Message->CompletionCallback = NULL;
|
|
||||||
Message->CompletionCallbackContext = 0;
|
|
||||||
Message->HookMessage = HookMessage;
|
Message->HookMessage = HookMessage;
|
||||||
Message->HasPackedLParam = FALSE;
|
Message->QS_Flags = QS_SENDMESSAGE;
|
||||||
|
|
||||||
/* Add it to the list of pending messages */
|
SaveMsg = pti->pusmSent;
|
||||||
InsertTailList(&pti->DispatchingMessagesHead, &Message->DispatchingListEntry);
|
pti->pusmSent = Message;
|
||||||
|
|
||||||
/* Queue it in the destination's message queue */
|
/* Queue it in the destination's message queue */
|
||||||
InsertTailList(&ptirec->SentMessagesListHead, &Message->ListEntry);
|
InsertTailList(&ptirec->SentMessagesListHead, &Message->ListEntry);
|
||||||
|
|
||||||
Message->QS_Flags = QS_SENDMESSAGE;
|
|
||||||
MsqWakeQueue(ptirec, QS_SENDMESSAGE, TRUE);
|
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)
|
if (Block)
|
||||||
{
|
{
|
||||||
PVOID WaitObjects[2];
|
PVOID WaitObjects[2];
|
||||||
|
|
||||||
WaitObjects[0] = &CompletionEvent; // Wait 0
|
WaitObjects[0] = Message->pkCompletionEvent; // Wait 0
|
||||||
WaitObjects[1] = ptirec->pEThread; // Wait 1
|
WaitObjects[1] = ptirec->pEThread; // Wait 1
|
||||||
|
|
||||||
UserLeaveCo();
|
UserLeaveCo();
|
||||||
|
|
||||||
WaitStatus = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, UserRequest,
|
WaitStatus = KeWaitForMultipleObjects( 2,
|
||||||
UserMode, FALSE, (uTimeout ? &Timeout : NULL), NULL);
|
WaitObjects,
|
||||||
|
WaitAny,
|
||||||
|
UserRequest,
|
||||||
|
UserMode,
|
||||||
|
FALSE,
|
||||||
|
(uTimeout ? &Timeout : NULL),
|
||||||
|
NULL );
|
||||||
|
|
||||||
UserEnterCo();
|
UserEnterCo();
|
||||||
|
|
||||||
|
@ -1168,39 +1201,24 @@ co_MsqSendMessage(PTHREADINFO ptirec,
|
||||||
{
|
{
|
||||||
if (CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry) == Message)
|
if (CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry) == Message)
|
||||||
{
|
{
|
||||||
/* We can access Message here, it's secure because the message queue is locked
|
Message->pkCompletionEvent = NULL;
|
||||||
and the message is still hasn't been dispatched */
|
|
||||||
Message->CompletionEvent = NULL;
|
|
||||||
Message->Result = NULL;
|
|
||||||
RemoveEntryList(&Message->ListEntry);
|
RemoveEntryList(&Message->ListEntry);
|
||||||
RemoveEntryList(&Message->DispatchingListEntry);
|
|
||||||
ClearMsgBitsMask(ptirec, Message->QS_Flags);
|
ClearMsgBitsMask(ptirec, Message->QS_Flags);
|
||||||
ExFreePoolWithTag(Message, TAG_USRMSG);
|
InsertTailList(&usmList, &Message->ListEntry);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Entry = Entry->Flink;
|
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.
|
// Receiving thread passed on and left us hanging with issues still pending.
|
||||||
else if (WaitStatus == STATUS_WAIT_1)
|
else if (WaitStatus == STATUS_WAIT_1)
|
||||||
{
|
{
|
||||||
ERR("Bk Receiving Thread woken up dead!\n");
|
ERR("Bk Receiving Thread woken up dead!\n");
|
||||||
Entry = pti->DispatchingMessagesHead.Flink;
|
Message->flags |= SMF_RECEIVERDIED;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (co_MsqDispatchOneSentMessage(pti))
|
while (co_MsqDispatchOneSentMessage(pti))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -1208,16 +1226,22 @@ co_MsqSendMessage(PTHREADINFO ptirec,
|
||||||
{
|
{
|
||||||
PVOID WaitObjects[3];
|
PVOID WaitObjects[3];
|
||||||
|
|
||||||
WaitObjects[0] = &CompletionEvent; // Wait 0
|
WaitObjects[0] = Message->pkCompletionEvent; // Wait 0
|
||||||
WaitObjects[1] = pti->pEventQueueServer; // Wait 1
|
WaitObjects[1] = pti->pEventQueueServer; // Wait 1
|
||||||
WaitObjects[2] = ptirec->pEThread; // Wait 2
|
WaitObjects[2] = ptirec->pEThread; // Wait 2
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
UserLeaveCo();
|
UserLeaveCo();
|
||||||
|
|
||||||
WaitStatus = KeWaitForMultipleObjects(3, WaitObjects, WaitAny, UserRequest,
|
WaitStatus = KeWaitForMultipleObjects( 3,
|
||||||
UserMode, FALSE, (uTimeout ? &Timeout : NULL), NULL);
|
WaitObjects,
|
||||||
|
WaitAny,
|
||||||
|
UserRequest,
|
||||||
|
UserMode,
|
||||||
|
FALSE,
|
||||||
|
(uTimeout ? &Timeout : NULL),
|
||||||
|
NULL);
|
||||||
|
|
||||||
UserEnterCo();
|
UserEnterCo();
|
||||||
|
|
||||||
|
@ -1230,41 +1254,23 @@ co_MsqSendMessage(PTHREADINFO ptirec,
|
||||||
{
|
{
|
||||||
if (CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry) == Message)
|
if (CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry) == Message)
|
||||||
{
|
{
|
||||||
/* We can access Message here, it's secure because the message queue is locked
|
Message->pkCompletionEvent = NULL;
|
||||||
and the message is still hasn't been dispatched */
|
|
||||||
Message->CompletionEvent = NULL;
|
|
||||||
Message->Result = NULL;
|
|
||||||
RemoveEntryList(&Message->ListEntry);
|
RemoveEntryList(&Message->ListEntry);
|
||||||
RemoveEntryList(&Message->DispatchingListEntry);
|
|
||||||
InitializeListHead(&Message->DispatchingListEntry);
|
|
||||||
ClearMsgBitsMask(ptirec, Message->QS_Flags);
|
ClearMsgBitsMask(ptirec, Message->QS_Flags);
|
||||||
ExFreePoolWithTag(Message, TAG_USRMSG);
|
InsertTailList(&usmList, &Message->ListEntry);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Entry = Entry->Flink;
|
Entry = Entry->Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("MsqSendMessage timed out 2 Status %lx\n", WaitStatus);
|
ERR("MsqSendMessage timed out 2 Status %lx\n", WaitStatus);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Receiving thread passed on and left us hanging with issues still pending.
|
// Receiving thread passed on and left us hanging with issues still pending.
|
||||||
else if (WaitStatus == STATUS_WAIT_2)
|
else if (WaitStatus == STATUS_WAIT_2)
|
||||||
{
|
{
|
||||||
ERR("NB Receiving Thread woken up dead!\n");
|
ERR("NB Receiving Thread woken up dead!\n");
|
||||||
Entry = pti->DispatchingMessagesHead.Flink;
|
Message->flags |= SMF_RECEIVERDIED;
|
||||||
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;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1275,19 +1281,52 @@ co_MsqSendMessage(PTHREADINFO ptirec,
|
||||||
} while (WaitStatus == STATUS_WAIT_1);
|
} 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)
|
if (WaitStatus == STATUS_USER_APC)
|
||||||
{
|
{
|
||||||
// The current thread is dying!
|
// The current thread is dying!
|
||||||
TRACE("User APC\n");
|
TRACE("User APC\n");
|
||||||
|
|
||||||
|
// The Message will be on the Trouble list until Thread cleanup.
|
||||||
|
Message->flags |= SMF_SENDERDIED;
|
||||||
|
|
||||||
co_IntDeliverUserAPC();
|
co_IntDeliverUserAPC();
|
||||||
ERR("User APC Returned\n"); // Should not see this message.
|
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 (WaitStatus != STATUS_TIMEOUT)
|
||||||
{
|
{
|
||||||
if (uResult)
|
if (uResult)
|
||||||
{
|
{
|
||||||
*uResult = (STATUS_WAIT_0 == WaitStatus ? Result : -1);
|
*uResult = (STATUS_WAIT_0 == WaitStatus ? Result : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2104,6 +2143,23 @@ MsqCleanupThreadMsgs(PTHREADINFO pti)
|
||||||
PUSER_MESSAGE CurrentMessage;
|
PUSER_MESSAGE CurrentMessage;
|
||||||
PUSER_SENT_MESSAGE CurrentSentMessage;
|
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 */
|
/* cleanup posted messages */
|
||||||
while (!IsListEmpty(&pti->PostedMessagesListHead))
|
while (!IsListEmpty(&pti->PostedMessagesListHead))
|
||||||
{
|
{
|
||||||
|
@ -2122,22 +2178,15 @@ MsqCleanupThreadMsgs(PTHREADINFO pti)
|
||||||
/* remove the messages that have not yet been dispatched */
|
/* remove the messages that have not yet been dispatched */
|
||||||
while (!IsListEmpty(&pti->SentMessagesListHead))
|
while (!IsListEmpty(&pti->SentMessagesListHead))
|
||||||
{
|
{
|
||||||
CurrentEntry = RemoveHeadList(&pti->SentMessagesListHead);
|
CurrentEntry = pti->SentMessagesListHead.Flink;
|
||||||
CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, ListEntry);
|
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");
|
ERR("Thread Cleanup Sent Messages\n");
|
||||||
/* Only if the message has a sender was the message in the DispatchingList */
|
|
||||||
if ((CurrentSentMessage->ptiSender) &&
|
|
||||||
(!IsListEmpty(&CurrentSentMessage->DispatchingListEntry)))
|
|
||||||
{
|
|
||||||
RemoveEntryList(&CurrentSentMessage->DispatchingListEntry);
|
|
||||||
InitializeListHead(&CurrentSentMessage->DispatchingListEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* wake the sender's thread */
|
/* wake the sender's thread */
|
||||||
if (CurrentSentMessage->CompletionEvent != NULL)
|
if (CurrentSentMessage->pkCompletionEvent != NULL)
|
||||||
{
|
{
|
||||||
KeSetEvent(CurrentSentMessage->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
KeSetEvent(CurrentSentMessage->pkCompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurrentSentMessage->HasPackedLParam)
|
if (CurrentSentMessage->HasPackedLParam)
|
||||||
|
@ -2147,71 +2196,49 @@ MsqCleanupThreadMsgs(PTHREADINFO pti)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free the message */
|
/* free the message */
|
||||||
ExFreePool(CurrentSentMessage);
|
FreeUserMessage(CurrentSentMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* notify senders of dispatching messages. This needs to be cleaned up if e.g.
|
// Process Trouble Message List
|
||||||
ExitThread() was called in a SendMessage() umode callback */
|
if (!IsListEmpty(&usmList))
|
||||||
while (!IsListEmpty(&pti->LocalDispatchingMessagesHead))
|
|
||||||
{
|
{
|
||||||
CurrentEntry = RemoveHeadList(&pti->LocalDispatchingMessagesHead);
|
CurrentEntry = usmList.Flink;
|
||||||
CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, ListEntry);
|
while (CurrentEntry != &usmList)
|
||||||
|
|
||||||
/* remove the message from the dispatching list */
|
|
||||||
if (!IsListEmpty(&CurrentSentMessage->DispatchingListEntry))
|
|
||||||
{
|
{
|
||||||
RemoveEntryList(&CurrentSentMessage->DispatchingListEntry);
|
CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, ListEntry);
|
||||||
InitializeListHead(&CurrentSentMessage->DispatchingListEntry);
|
CurrentEntry = CurrentEntry->Flink;
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("Notify the sender, the thread has been terminated while dispatching a message!\n");
|
TRACE("Found troubled messages on the list\n");
|
||||||
|
|
||||||
/* wake the sender's thread */
|
if ( pti == CurrentSentMessage->ptiReceiver )
|
||||||
if (CurrentSentMessage->CompletionEvent != NULL)
|
|
||||||
{
|
|
||||||
KeSetEvent(CurrentSentMessage->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CurrentSentMessage->HasPackedLParam)
|
|
||||||
{
|
|
||||||
if (CurrentSentMessage->Msg.lParam)
|
|
||||||
{
|
{
|
||||||
_PRAGMA_WARNING_SUPPRESS(__WARNING_USING_UNINIT_VAR);
|
if (CurrentSentMessage->HasPackedLParam)
|
||||||
ExFreePool((PVOID)CurrentSentMessage->Msg.lParam);
|
{
|
||||||
|
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
|
VOID FASTCALL
|
||||||
|
@ -2364,7 +2391,7 @@ co_MsqReplyMessage( LRESULT lResult )
|
||||||
|
|
||||||
if (Message->QS_Flags & QS_SMRESULT) return FALSE;
|
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)
|
if (Message->ptiSender || Message->CompletionCallback)
|
||||||
{
|
{
|
||||||
Message->lResult = lResult;
|
Message->lResult = lResult;
|
||||||
|
|
|
@ -22,20 +22,25 @@ typedef struct _USER_SENT_MESSAGE
|
||||||
LIST_ENTRY ListEntry;
|
LIST_ENTRY ListEntry;
|
||||||
MSG Msg;
|
MSG Msg;
|
||||||
DWORD QS_Flags; // Original QS bits used to create this message.
|
DWORD QS_Flags; // Original QS bits used to create this message.
|
||||||
PKEVENT CompletionEvent;
|
PKEVENT pkCompletionEvent;
|
||||||
LRESULT* Result;
|
|
||||||
LRESULT lResult;
|
LRESULT lResult;
|
||||||
|
DWORD flags;
|
||||||
PTHREADINFO ptiSender;
|
PTHREADINFO ptiSender;
|
||||||
PTHREADINFO ptiReceiver;
|
PTHREADINFO ptiReceiver;
|
||||||
SENDASYNCPROC CompletionCallback;
|
SENDASYNCPROC CompletionCallback;
|
||||||
PTHREADINFO ptiCallBackSender;
|
PTHREADINFO ptiCallBackSender;
|
||||||
ULONG_PTR CompletionCallbackContext;
|
ULONG_PTR CompletionCallbackContext;
|
||||||
/* entry in the dispatching list of the sender's message queue */
|
|
||||||
LIST_ENTRY DispatchingListEntry;
|
|
||||||
INT HookMessage;
|
INT HookMessage;
|
||||||
BOOL HasPackedLParam;
|
BOOL HasPackedLParam;
|
||||||
|
KEVENT CompletionEvent;
|
||||||
} USER_SENT_MESSAGE, *PUSER_SENT_MESSAGE;
|
} 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
|
typedef struct _USER_MESSAGE_QUEUE
|
||||||
{
|
{
|
||||||
/* Reference counter, only access this variable with interlocked functions! */
|
/* Reference counter, only access this variable with interlocked functions! */
|
||||||
|
@ -117,6 +122,8 @@ enum internal_event_message
|
||||||
|
|
||||||
#define POSTEVENT_NWE 14
|
#define POSTEVENT_NWE 14
|
||||||
|
|
||||||
|
extern LIST_ENTRY usmList;
|
||||||
|
|
||||||
BOOL FASTCALL MsqIsHung(PTHREADINFO pti);
|
BOOL FASTCALL MsqIsHung(PTHREADINFO pti);
|
||||||
VOID CALLBACK HungAppSysTimerProc(HWND,UINT,UINT_PTR,DWORD);
|
VOID CALLBACK HungAppSysTimerProc(HWND,UINT,UINT_PTR,DWORD);
|
||||||
NTSTATUS FASTCALL co_MsqSendMessage(PTHREADINFO ptirec,
|
NTSTATUS FASTCALL co_MsqSendMessage(PTHREADINFO ptirec,
|
||||||
|
@ -252,6 +259,9 @@ VOID FASTCALL ClearMsgBitsMask(PTHREADINFO,UINT);
|
||||||
BOOL FASTCALL IntCallMsgFilter(LPMSG,INT);
|
BOOL FASTCALL IntCallMsgFilter(LPMSG,INT);
|
||||||
WPARAM FASTCALL MsqGetDownKeyState(PUSER_MESSAGE_QUEUE);
|
WPARAM FASTCALL MsqGetDownKeyState(PUSER_MESSAGE_QUEUE);
|
||||||
BOOL FASTCALL IsThreadSuspended(PTHREADINFO);
|
BOOL FASTCALL IsThreadSuspended(PTHREADINFO);
|
||||||
|
PUSER_SENT_MESSAGE FASTCALL AllocateUserMessage(BOOL);
|
||||||
|
VOID FASTCALL FreeUserMessage(PUSER_SENT_MESSAGE);
|
||||||
|
|
||||||
|
|
||||||
int UserShowCursor(BOOL bShow);
|
int UserShowCursor(BOOL bShow);
|
||||||
PCURICON_OBJECT
|
PCURICON_OBJECT
|
||||||
|
|
|
@ -93,8 +93,7 @@ typedef struct _THREADINFO
|
||||||
struct _CLIENTINFO * pClientInfo;
|
struct _CLIENTINFO * pClientInfo;
|
||||||
FLONG TIF_flags;
|
FLONG TIF_flags;
|
||||||
PUNICODE_STRING pstrAppName;
|
PUNICODE_STRING pstrAppName;
|
||||||
/* Messages that are currently dispatched to other threads */
|
struct _USER_SENT_MESSAGE *pusmSent;
|
||||||
LIST_ENTRY DispatchingMessagesHead; // psmsSent
|
|
||||||
struct _USER_SENT_MESSAGE *pusmCurrent;
|
struct _USER_SENT_MESSAGE *pusmCurrent;
|
||||||
/* Queue of messages sent to the queue. */
|
/* Queue of messages sent to the queue. */
|
||||||
LIST_ENTRY SentMessagesListHead; // psmsReceiveList
|
LIST_ENTRY SentMessagesListHead; // psmsReceiveList
|
||||||
|
@ -127,6 +126,7 @@ typedef struct _THREADINFO
|
||||||
INT iCursorLevel;
|
INT iCursorLevel;
|
||||||
POINT ptLast;
|
POINT ptLast;
|
||||||
|
|
||||||
|
INT cEnterCount;
|
||||||
/* Queue of messages posted to the queue. */
|
/* Queue of messages posted to the queue. */
|
||||||
LIST_ENTRY PostedMessagesListHead; // mlPost
|
LIST_ENTRY PostedMessagesListHead; // mlPost
|
||||||
WORD fsChangeBitsRemoved;
|
WORD fsChangeBitsRemoved;
|
||||||
|
@ -146,8 +146,6 @@ typedef struct _THREADINFO
|
||||||
// Accounting of queue bit sets, the rest are flags. QS_TIMER QS_PAINT counts are handled in thread information.
|
// 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
|
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 WindowListHead;
|
||||||
LIST_ENTRY W32CallbackListHead;
|
LIST_ENTRY W32CallbackListHead;
|
||||||
SINGLE_LIST_ENTRY ReferencesList;
|
SINGLE_LIST_ENTRY ReferencesList;
|
||||||
|
|
Loading…
Reference in a new issue