- 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; PTHREADINFO ptiMouse;
PKTIMER MasterTimer = NULL; PKTIMER MasterTimer = NULL;
PATTACHINFO gpai = NULL; PATTACHINFO gpai = NULL;
INT paiCount = 0;
HANDLE ghKeyboardDevice; HANDLE ghKeyboardDevice;
static DWORD LastInputTick = 0; static DWORD LastInputTick = 0;
@ -414,20 +415,20 @@ IsThreadAttach(PTHREADINFO ptiTo)
return pai->pti1; return pai->pti1;
} }
BOOL FASTCALL NTSTATUS FASTCALL
UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach) UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
{ {
MSG msg; MSG msg;
PATTACHINFO pai; PATTACHINFO pai;
/* Can not be the same thread. */ /* 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. */ /* Do not attach to system threads or between different desktops. */
if (ptiFrom->TIF_flags & TIF_DONTATTACHQUEUE || if (ptiFrom->TIF_flags & TIF_DONTATTACHQUEUE ||
ptiTo->TIF_flags & TIF_DONTATTACHQUEUE || ptiTo->TIF_flags & TIF_DONTATTACHQUEUE ||
ptiFrom->rpdesk != ptiTo->rpdesk) ptiFrom->rpdesk != ptiTo->rpdesk)
return FALSE; return STATUS_ACCESS_DENIED;
/* MSDN Note: /* MSDN Note:
Keyboard and mouse events received by both threads are processed by the thread specified by the idAttachTo. 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) if (fAttach)
{ {
pai = ExAllocatePoolWithTag(PagedPool, sizeof(ATTACHINFO), USERTAG_ATTACHINFO); pai = ExAllocatePoolWithTag(PagedPool, sizeof(ATTACHINFO), USERTAG_ATTACHINFO);
if (!pai) return FALSE; if (!pai) return STATUS_NO_MEMORY;
pai->paiNext = gpai; pai->paiNext = gpai;
pai->pti1 = ptiFrom; pai->pti1 = ptiFrom;
pai->pti2 = ptiTo; pai->pti2 = ptiTo;
gpai = pai; 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; ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
/* Keep the original queue in pqAttach (ie do not trash it in a second attachment) */
if (ptiFrom->pqAttach == NULL)
ptiFrom->pqAttach = ptiFrom->MessageQueue; ptiFrom->pqAttach = ptiFrom->MessageQueue;
ptiFrom->MessageQueue = ptiTo->MessageQueue; ptiFrom->MessageQueue = ptiTo->MessageQueue;
ptiFrom->MessageQueue->cThreads++;
ERR("ptiTo S Share count %d\n", ptiFrom->MessageQueue->cThreads);
// FIXME: conditions? // FIXME: conditions?
if (ptiFrom->pqAttach == gpqForeground) if (ptiFrom->pqAttach == gpqForeground)
{ {
ERR("ptiFrom is Foreground\n");
ptiFrom->MessageQueue->spwndActive = ptiFrom->pqAttach->spwndActive; ptiFrom->MessageQueue->spwndActive = ptiFrom->pqAttach->spwndActive;
ptiFrom->MessageQueue->spwndFocus = ptiFrom->pqAttach->spwndFocus; ptiFrom->MessageQueue->spwndFocus = ptiFrom->pqAttach->spwndFocus;
ptiFrom->MessageQueue->CursorObject = ptiFrom->pqAttach->CursorObject; 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->QF_flags ^= ((ptiFrom->MessageQueue->QF_flags ^ ptiFrom->pqAttach->QF_flags) & QF_CAPTURELOCKED);
ptiFrom->MessageQueue->CaretInfo = ptiFrom->pqAttach->CaretInfo; 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. */ else /* If clear, unlink and free it. */
{ {
PATTACHINFO paiprev = NULL; BOOL Hit = FALSE;
PATTACHINFO *ppai;
if (!gpai) return FALSE; if (!gpai) return STATUS_INVALID_PARAMETER;
pai = gpai;
/* Search list and free if found or return false. */ /* Search list and free if found or return false. */
do ppai = &gpai;
while (*ppai != NULL)
{ {
if (pai->pti2 == ptiTo && pai->pti1 == ptiFrom) break; if ( (*ppai)->pti2 == ptiTo && (*ppai)->pti1 == ptiFrom )
paiprev = pai; {
pai = pai->paiNext; pai = *ppai;
} while (pai); /* Remove it from the list */
*ppai = (*ppai)->paiNext;
if (!pai) return FALSE;
if (paiprev) paiprev->paiNext = pai->paiNext;
else if (!pai->paiNext) gpai = NULL;
ExFreePoolWithTag(pai, USERTAG_ATTACHINFO); ExFreePoolWithTag(pai, USERTAG_ATTACHINFO);
ERR("Attach Free! ptiFrom 0x%p ptiTo 0x%p\n",ptiFrom,ptiTo); 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;
}
ptiFrom->MessageQueue->cThreads--;
ERR("ptiTo E Share count %d\n", ptiFrom->MessageQueue->cThreads);
ptiFrom->MessageQueue = ptiFrom->pqAttach; ptiFrom->MessageQueue = ptiFrom->pqAttach;
// FIXME: conditions? // FIXME: conditions?
ptiFrom->MessageQueue->CursorObject = NULL; ptiFrom->MessageQueue->CursorObject = NULL;
@ -505,7 +560,7 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
msg.pt = gpsi->ptCursor; msg.pt = gpsi->ptCursor;
co_MsqInsertMouseMessage(&msg, 0, 0, TRUE); 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); INIT_FUNCTION NTSTATUS NTAPI InitInputImpl(VOID);
BOOL FASTCALL IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt); BOOL FASTCALL IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt);
DWORD NTAPI CreateSystemThreads(UINT Type); DWORD NTAPI CreateSystemThreads(UINT Type);
BOOL FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL); NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL);
PTHREADINFO FASTCALL IsThreadAttach(PTHREADINFO); PTHREADINFO FASTCALL IsThreadAttach(PTHREADINFO);
VOID FASTCALL DoTheScreenSaver(VOID); VOID FASTCALL DoTheScreenSaver(VOID);
#define ThreadHasInputAccess(W32Thread) (TRUE) #define ThreadHasInputAccess(W32Thread) (TRUE)

View file

@ -401,6 +401,28 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread)
ppiCurrent = ptiCurrent->ppi; ppiCurrent = ptiCurrent->ppi;
ASSERT(ppiCurrent); 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 */ /* Decrement thread count and check if its 0 */
ppiCurrent->cThreads--; 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 */ /* Free the message queue */
if (ptiCurrent->MessageQueue) if (ptiCurrent->MessageQueue)
{ {

View file

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