- AttachThreadInput, this should fix the crash. Original crash patch by Giannis Adamopoulos. See bug 7225.
- WARNING: This code should be turned off until the restructuring is finished. Please read bug 7225!

svn path=/trunk/; revision=57103
This commit is contained in:
James Tabor 2012-08-18 22:13:38 +00:00
parent 5d164caee1
commit f9da00bc86
4 changed files with 111 additions and 44 deletions

View file

@ -17,6 +17,7 @@ PTHREADINFO ptiKeyboard;
PTHREADINFO ptiMouse;
PKTIMER MasterTimer = NULL;
PATTACHINFO gpai = NULL;
INT paiCount = 0;
HANDLE ghKeyboardDevice;
static DWORD LastInputTick = 0;
@ -414,20 +415,20 @@ IsThreadAttach(PTHREADINFO ptiTo)
return pai->pti1;
}
BOOL FASTCALL
NTSTATUS FASTCALL
UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
{
MSG msg;
PATTACHINFO pai;
/* Can not be the same thread. */
if (ptiFrom == ptiTo) return FALSE;
if (ptiFrom == ptiTo) return STATUS_INVALID_PARAMETER;
/* Do not attach to system threads or between different desktops. */
if (ptiFrom->TIF_flags & TIF_DONTATTACHQUEUE ||
ptiTo->TIF_flags & TIF_DONTATTACHQUEUE ||
ptiFrom->rpdesk != ptiTo->rpdesk)
return FALSE;
ptiTo->TIF_flags & TIF_DONTATTACHQUEUE ||
ptiFrom->rpdesk != ptiTo->rpdesk)
return STATUS_ACCESS_DENIED;
/* MSDN Note:
Keyboard and mouse events received by both threads are processed by the thread specified by the idAttachTo.
@ -437,20 +438,34 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
if (fAttach)
{
pai = ExAllocatePoolWithTag(PagedPool, sizeof(ATTACHINFO), USERTAG_ATTACHINFO);
if (!pai) return FALSE;
if (!pai) return STATUS_NO_MEMORY;
pai->paiNext = gpai;
pai->pti1 = ptiFrom;
pai->pti2 = ptiTo;
gpai = pai;
ERR("Attach Allocated! ptiFrom 0x%p ptiTo 0x%p\n",ptiFrom,ptiTo);
paiCount++;
ERR("Attach Allocated! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
if (ptiTo->MessageQueue == ptiFrom->MessageQueue)
{
ERR("Attach Threads are already associated!\n");
}
ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
ptiFrom->pqAttach = ptiFrom->MessageQueue;
/* Keep the original queue in pqAttach (ie do not trash it in a second attachment) */
if (ptiFrom->pqAttach == NULL)
ptiFrom->pqAttach = ptiFrom->MessageQueue;
ptiFrom->MessageQueue = ptiTo->MessageQueue;
ptiFrom->MessageQueue->cThreads++;
ERR("ptiTo S Share count %d\n", ptiFrom->MessageQueue->cThreads);
// FIXME: conditions?
if (ptiFrom->pqAttach == gpqForeground)
{
ERR("ptiFrom is Foreground\n");
ptiFrom->MessageQueue->spwndActive = ptiFrom->pqAttach->spwndActive;
ptiFrom->MessageQueue->spwndFocus = ptiFrom->pqAttach->spwndFocus;
ptiFrom->MessageQueue->CursorObject = ptiFrom->pqAttach->CursorObject;
@ -458,31 +473,71 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
ptiFrom->MessageQueue->QF_flags ^= ((ptiFrom->MessageQueue->QF_flags ^ ptiFrom->pqAttach->QF_flags) & QF_CAPTURELOCKED);
ptiFrom->MessageQueue->CaretInfo = ptiFrom->pqAttach->CaretInfo;
}
else
{
ERR("ptiFrom NOT Foreground\n");
}
if (ptiTo->MessageQueue == gpqForeground)
{
ERR("ptiTo is Foreground\n");
}
else
{
ERR("ptiTo NOT Foreground\n");
}
}
else /* If clear, unlink and free it. */
{
PATTACHINFO paiprev = NULL;
BOOL Hit = FALSE;
PATTACHINFO *ppai;
if (!gpai) return FALSE;
pai = gpai;
if (!gpai) return STATUS_INVALID_PARAMETER;
/* Search list and free if found or return false. */
do
ppai = &gpai;
while (*ppai != NULL)
{
if (pai->pti2 == ptiTo && pai->pti1 == ptiFrom) break;
paiprev = pai;
if ( (*ppai)->pti2 == ptiTo && (*ppai)->pti1 == ptiFrom )
{
pai = *ppai;
/* Remove it from the list */
*ppai = (*ppai)->paiNext;
ExFreePoolWithTag(pai, USERTAG_ATTACHINFO);
paiCount--;
Hit = TRUE;
break;
}
ppai = &((*ppai)->paiNext);
}
if (!Hit) return STATUS_INVALID_PARAMETER;
ASSERT(ptiFrom->pqAttach);
ERR("Attach Free! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
/* Search list and check if the thread is attached one more time */
pai = gpai;
while(pai)
{
/* If the thread is attached again , we are done */
if (pai->pti1 == ptiFrom)
{
ptiFrom->MessageQueue->cThreads--;
ERR("ptiTo L Share count %d\n", ptiFrom->MessageQueue->cThreads);
/* Use the message queue of the last attachment */
ptiFrom->MessageQueue = pai->pti2->MessageQueue;
ptiFrom->MessageQueue->CursorObject = NULL;
ptiFrom->MessageQueue->spwndActive = NULL;
ptiFrom->MessageQueue->spwndFocus = NULL;
ptiFrom->MessageQueue->spwndCapture = NULL;
return STATUS_SUCCESS;
}
pai = pai->paiNext;
} while (pai);
if (!pai) return FALSE;
if (paiprev) paiprev->paiNext = pai->paiNext;
else if (!pai->paiNext) gpai = NULL;
ExFreePoolWithTag(pai, USERTAG_ATTACHINFO);
ERR("Attach Free! ptiFrom 0x%p ptiTo 0x%p\n",ptiFrom,ptiTo);
}
ptiFrom->MessageQueue->cThreads--;
ERR("ptiTo E Share count %d\n", ptiFrom->MessageQueue->cThreads);
ptiFrom->MessageQueue = ptiFrom->pqAttach;
// FIXME: conditions?
ptiFrom->MessageQueue->CursorObject = NULL;
@ -505,7 +560,7 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
msg.pt = gpsi->ptCursor;
co_MsqInsertMouseMessage(&msg, 0, 0, TRUE);
return TRUE;
return STATUS_SUCCESS;
}
/*

View file

@ -62,7 +62,7 @@ extern PATTACHINFO gpai;
INIT_FUNCTION NTSTATUS NTAPI InitInputImpl(VOID);
BOOL FASTCALL IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt);
DWORD NTAPI CreateSystemThreads(UINT Type);
BOOL FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL);
NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL);
PTHREADINFO FASTCALL IsThreadAttach(PTHREADINFO);
VOID FASTCALL DoTheScreenSaver(VOID);
#define ThreadHasInputAccess(W32Thread) (TRUE)

View file

@ -401,6 +401,28 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread)
ppiCurrent = ptiCurrent->ppi;
ASSERT(ppiCurrent);
// ptiTo
if (IsThreadAttach(ptiCurrent))
{
PTHREADINFO ptiFrom = IsThreadAttach(ptiCurrent);
TRACE_CH(UserThread,"Attached Thread ptiTo is getting switched!\n");
UserAttachThreadInput(ptiFrom, ptiCurrent, FALSE);
}
// ptiFrom
if (ptiCurrent->pqAttach && ptiCurrent->MessageQueue)
{
PTHREADINFO ptiTo;
ptiTo = PsGetThreadWin32Thread(ptiCurrent->MessageQueue->Thread);
TRACE_CH(UserThread,"Attached Thread ptiFrom is getting switched!\n");
if (ptiTo) UserAttachThreadInput( ptiCurrent, ptiTo, FALSE);
else
{
// eThread maybe okay but Win32Thread already made NULL!
ERR_CH(UserThread,"Attached Thread ptiFrom did not switch due to ptiTo is NULL!\n");
}
}
/* Decrement thread count and check if its 0 */
ppiCurrent->cThreads--;
@ -472,23 +494,6 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread)
}
}
// ptiTo
if (IsThreadAttach(ptiCurrent))
{
PTHREADINFO ptiFrom = IsThreadAttach(ptiCurrent);
TRACE_CH(UserThread,"Attached Thread ptiTo is getting switched!\n");
UserAttachThreadInput(ptiFrom, ptiCurrent, FALSE);
}
// ptiFrom
if (ptiCurrent->pqAttach && ptiCurrent->MessageQueue)
{
PTHREADINFO ptiTo;
ptiTo = PsGetThreadWin32Thread(ptiCurrent->MessageQueue->Thread);
TRACE_CH(UserThread,"Attached Thread ptiFrom is getting switched!\n");
UserAttachThreadInput( ptiCurrent, ptiTo, FALSE);
}
/* Free the message queue */
if (ptiCurrent->MessageQueue)
{

View file

@ -34,6 +34,7 @@ NtUserAttachThreadInput(
BOOL Ret = FALSE;
UserEnterExclusive();
ERR("Enter NtUserAttachThreadInput %s\n",(fAttach ? "TRUE" : "FALSE" ));
Status = PsLookupThreadByThreadId((HANDLE)idAttach, &Thread);
if (!NT_SUCCESS(Status))
{
@ -53,9 +54,15 @@ NtUserAttachThreadInput(
ObDereferenceObject(Thread);
ObDereferenceObject(ThreadTo);
Ret = UserAttachThreadInput( pti, ptiTo, fAttach);
Status = UserAttachThreadInput( pti, ptiTo, fAttach);
if (!NT_SUCCESS(Status))
{
EngSetLastError(RtlNtStatusToDosError(Status));
}
else Ret = TRUE;
Exit:
ERR("Leave NtUserAttachThreadInput, ret=%d\n",Ret);
UserLeave();
return Ret;
}