mirror of
https://github.com/reactos/reactos.git
synced 2024-06-29 01:12:06 +00:00
[Win32k]
- Crash is due to receiving an APC for the current sending thread. Prematurely freeing the data block and while the receiving thread did not have a chance to process it. Interception and calling back to user mode will allow thread to go away. What about the memory block, is it still allocated? A cleaver Hack can fix this, but still the application crashed leaving issues and trash laying about. See CORE-8779. Reference: http://msdn.microsoft.com/en-us/library/windows/hardware/ff565592(v=vs.85).aspx "Yes, for thread termination. No, for user APCs." svn path=/trunk/; revision=65744
This commit is contained in:
parent
9bc240e832
commit
b037edeae8
|
@ -13,7 +13,8 @@
|
|||
#define USER32_CALLBACK_GETCHARSETINFO (9)
|
||||
#define USER32_CALLBACK_COPYIMAGE (10)
|
||||
#define USER32_CALLBACK_SETWNDICONS (11)
|
||||
#define USER32_CALLBACK_MAXIMUM (11)
|
||||
#define USER32_CALLBACK_DELIVERUSERAPC (12)
|
||||
#define USER32_CALLBACK_MAXIMUM (12)
|
||||
|
||||
typedef struct _WINDOWPROC_CALLBACK_ARGUMENTS
|
||||
{
|
||||
|
@ -138,4 +139,6 @@ NTSTATUS WINAPI
|
|||
User32CallClientLoadLibraryFromKernel(PVOID Arguments, ULONG ArgumentLength);
|
||||
NTSTATUS WINAPI
|
||||
User32CallGetCharsetInfo(PVOID Arguments, ULONG ArgumentLength);
|
||||
NTSTATUS WINAPI
|
||||
User32DeliverUserAPC(PVOID Arguments, ULONG ArgumentLength);
|
||||
#endif /* __INCLUDE_USER32_CALLBACK_H */
|
||||
|
|
|
@ -1100,4 +1100,24 @@ co_IntSetWndIcons(VOID)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
co_IntDeliverUserAPC(VOID)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
UserLeaveCo();
|
||||
|
||||
Status = KeUserModeCallback(USER32_CALLBACK_DELIVERUSERAPC,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
|
||||
UserEnterCo();
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("Delivering User APC callback failed!\n");
|
||||
}
|
||||
}
|
||||
/* EOF */
|
||||
|
|
|
@ -71,3 +71,4 @@ co_IntGetCharsetInfo(LCID Locale, PCHARSETINFO pCs);
|
|||
HANDLE FASTCALL co_IntCopyImage(HANDLE,UINT,INT,INT,UINT);
|
||||
|
||||
BOOL FASTCALL co_IntSetWndIcons(VOID);
|
||||
VOID FASTCALL co_IntDeliverUserAPC(VOID);
|
||||
|
|
|
@ -1132,17 +1132,22 @@ co_MsqSendMessage(PTHREADINFO ptirec,
|
|||
|
||||
/* We can't access the Message anymore since it could have already been deleted! */
|
||||
|
||||
if(Block)
|
||||
if (Block)
|
||||
{
|
||||
PVOID WaitObjects[2];
|
||||
|
||||
WaitObjects[0] = &CompletionEvent; // Wait 0
|
||||
WaitObjects[1] = ptirec->pEThread; // Wait 1
|
||||
|
||||
UserLeaveCo();
|
||||
|
||||
/* Don't process messages sent to the thread */
|
||||
WaitStatus = KeWaitForSingleObject(&CompletionEvent, UserRequest, UserMode,
|
||||
FALSE, (uTimeout ? &Timeout : NULL));
|
||||
WaitStatus = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, UserRequest,
|
||||
UserMode, FALSE, (uTimeout ? &Timeout : NULL), NULL);
|
||||
|
||||
UserEnterCo();
|
||||
|
||||
if(WaitStatus == STATUS_TIMEOUT)
|
||||
if (WaitStatus == STATUS_TIMEOUT || WaitStatus == STATUS_USER_APC)
|
||||
{
|
||||
/* Look up if the message has not yet dispatched, if so
|
||||
make sure it can't pass a result and it must not set the completion event anymore */
|
||||
|
@ -1182,7 +1187,27 @@ co_MsqSendMessage(PTHREADINFO ptirec,
|
|||
Entry = Entry->Flink;
|
||||
}
|
||||
|
||||
TRACE("MsqSendMessage (blocked) timed out 1\n");
|
||||
TRACE("MsqSendMessage (blocked) timed out 1 Status %p\n",WaitStatus);
|
||||
|
||||
}
|
||||
// Receiving thread passed on and left us hanging with issues still pending.
|
||||
if ( WaitStatus == STATUS_WAIT_1 )
|
||||
{
|
||||
ERR("Bk Receiving Thread woken up dead!\n");
|
||||
Entry = pti->DispatchingMessagesHead.Flink;
|
||||
while (Entry != &pti->DispatchingMessagesHead)
|
||||
{
|
||||
if ((PUSER_SENT_MESSAGE) CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, DispatchingListEntry)
|
||||
== Message)
|
||||
{
|
||||
Message->CompletionEvent = NULL;
|
||||
Message->Result = NULL;
|
||||
RemoveEntryList(&Message->DispatchingListEntry);
|
||||
Message->DispatchingListEntry.Flink = NULL;
|
||||
break;
|
||||
}
|
||||
Entry = Entry->Flink;
|
||||
}
|
||||
}
|
||||
while (co_MsqDispatchOneSentMessage(pti))
|
||||
;
|
||||
|
@ -1204,7 +1229,7 @@ co_MsqSendMessage(PTHREADINFO ptirec,
|
|||
|
||||
UserEnterCo();
|
||||
|
||||
if(WaitStatus == STATUS_TIMEOUT)
|
||||
if (WaitStatus == STATUS_TIMEOUT || WaitStatus == STATUS_USER_APC)
|
||||
{
|
||||
/* Look up if the message has not yet been dispatched, if so
|
||||
make sure it can't pass a result and it must not set the completion event anymore */
|
||||
|
@ -1244,13 +1269,14 @@ co_MsqSendMessage(PTHREADINFO ptirec,
|
|||
Entry = Entry->Flink;
|
||||
}
|
||||
|
||||
TRACE("MsqSendMessage timed out 2\n");
|
||||
TRACE("MsqSendMessage timed out 2 Status %p\n",WaitStatus);
|
||||
|
||||
break;
|
||||
}
|
||||
// Receiving thread passed on and left us hanging with issues still pending.
|
||||
if ( WaitStatus == STATUS_WAIT_2 )
|
||||
{
|
||||
ERR("Receiving Thread woken up dead!\n");
|
||||
ERR("NB Receiving Thread woken up dead!\n");
|
||||
Entry = pti->DispatchingMessagesHead.Flink;
|
||||
while (Entry != &pti->DispatchingMessagesHead)
|
||||
{
|
||||
|
@ -1272,8 +1298,21 @@ co_MsqSendMessage(PTHREADINFO ptirec,
|
|||
while (NT_SUCCESS(WaitStatus) && WaitStatus == STATUS_WAIT_1);
|
||||
}
|
||||
|
||||
if(WaitStatus != STATUS_TIMEOUT)
|
||||
if (uResult) *uResult = (STATUS_WAIT_0 == WaitStatus ? Result : -1);
|
||||
if ( WaitStatus == STATUS_USER_APC )
|
||||
{
|
||||
// The current thread is dying!
|
||||
TRACE("User APC\n");
|
||||
co_IntDeliverUserAPC();
|
||||
ERR("User APC Returned\n"); // Should not see this message.
|
||||
}
|
||||
|
||||
if (WaitStatus != STATUS_TIMEOUT)
|
||||
{
|
||||
if (uResult)
|
||||
{
|
||||
*uResult = (STATUS_WAIT_0 == WaitStatus ? Result : -1);
|
||||
}
|
||||
}
|
||||
|
||||
return WaitStatus;
|
||||
}
|
||||
|
@ -1972,6 +2011,11 @@ co_MsqWaitForNewMessages(PTHREADINFO pti, PWND WndFilter,
|
|||
FALSE,
|
||||
NULL );
|
||||
UserEnterCo();
|
||||
if ( ret == STATUS_USER_APC )
|
||||
{
|
||||
TRACE("MWFNW User APC\n");
|
||||
co_IntDeliverUserAPC();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -200,6 +200,7 @@ PVOID apfnDispatch[USER32_CALLBACK_MAXIMUM + 1] =
|
|||
User32CallGetCharsetInfo,
|
||||
User32CallCopyImageFromKernel,
|
||||
User32CallSetWndIconsFromKernel,
|
||||
User32DeliverUserAPC,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -468,3 +469,10 @@ User32CallSetWndIconsFromKernel(PVOID Arguments, ULONG ArgumentLength)
|
|||
ERR("hIconSmWindows %p hIconWindows %p \n",hIconSmWindows,hIconWindows);
|
||||
return ZwCallbackReturn(Arguments, ArgumentLength, STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
WINAPI
|
||||
User32DeliverUserAPC(PVOID Arguments, ULONG ArgumentLength)
|
||||
{
|
||||
return ZwCallbackReturn(0, 0, STATUS_SUCCESS);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue