[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:
James Tabor 2015-11-03 15:18:51 +00:00
parent 8584094adc
commit 598aff78e9
7 changed files with 334 additions and 282 deletions

View file

@ -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

View file

@ -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;
} }
} }

View file

@ -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)

View file

@ -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)
{ {

View file

@ -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;

View file

@ -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

View file

@ -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;